blob: ae841c8c676312115cb89248d42b39e9fb2f2d34 [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
Daniel Veillard3c558c31999-12-22 11:30:41 +000010#include "win32config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000011#else
Daniel Veillard151b1b01998-09-23 00:49:46 +000012#include "config.h"
Daniel Veillard7f7d1111999-09-22 09:46:25 +000013#endif
14
Daniel Veillard260a68f1998-08-13 03:39:55 +000015#include <stdio.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000016#include <string.h> /* for memset() only ! */
17
Daniel Veillard7f7d1111999-09-22 09:46:25 +000018#ifdef HAVE_CTYPE_H
19#include <ctype.h>
20#endif
21#ifdef HAVE_STDLIB_H
22#include <stdlib.h>
23#endif
Daniel Veillard151b1b01998-09-23 00:49:46 +000024#ifdef HAVE_ZLIB_H
25#include <zlib.h>
26#endif
27
Daniel Veillard361d8452000-04-03 19:48:13 +000028#include <libxml/xmlmemory.h>
29#include <libxml/tree.h>
30#include <libxml/parser.h>
31#include <libxml/entities.h>
32#include <libxml/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 Veillardcf461992000-03-14 18:30:20 +000035static xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
Daniel Veillard260a68f1998-08-13 03:39:55 +000036int oldXMLWDcompatibility = 0;
Daniel Veillardcf461992000-03-14 18:30:20 +000037int xmlIndentTreeOutput = 0;
Daniel Veillardf5c2c871999-12-01 09:51:45 +000038xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
Daniel Veillard260a68f1998-08-13 03:39:55 +000039
Daniel Veillard15a8df41998-09-24 19:15:06 +000040static int xmlCompressMode = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +000041static int xmlCheckDTD = 1;
Daniel Veillarde41f2b72000-01-30 20:00:07 +000042int xmlSaveNoEmptyTags = 0;
Daniel Veillard3e6d2372000-03-04 11:39:43 +000043
44#define IS_BLANK(c) \
45 (((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
Daniel Veillard15a8df41998-09-24 19:15:06 +000046
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000047#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
Daniel Veillardcf461992000-03-14 18:30:20 +000048 xmlNodePtr ulccur = (n)->children; \
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000049 if (ulccur == NULL) { \
50 (n)->last = NULL; \
51 } else { \
52 while (ulccur->next != NULL) ulccur = ulccur->next; \
53 (n)->last = ulccur; \
Daniel Veillard1e346af1999-02-22 10:33:01 +000054}}
Daniel Veillard39a1f9a1999-01-17 19:11:59 +000055
Daniel Veillardad8f99d2000-01-15 14:20:03 +000056/* #define DEBUG_BUFFER */
57/* #define DEBUG_TREE */
58
Daniel Veillard260a68f1998-08-13 03:39:55 +000059/************************************************************************
60 * *
61 * Allocation and deallocation of basic structures *
62 * *
63 ************************************************************************/
64
Daniel Veillard97b58771998-10-20 06:14:16 +000065/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +000066 * xmlSetBufferAllocationScheme:
67 * @scheme: allocation method to use
68 *
69 * Set the buffer allocation method. Types are
70 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
71 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
72 * improves performance
73 */
74void
75xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
76 xmlBufferAllocScheme = scheme;
77}
78
79/**
80 * xmlGetBufferAllocationScheme:
81 *
82 * Types are
83 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
84 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
85 * improves performance
86 *
87 * Returns the current allocation scheme
88 */
89xmlBufferAllocationScheme
90xmlGetBufferAllocationScheme() {
91 return xmlBufferAllocScheme;
92}
93
94/**
Daniel Veillard97b58771998-10-20 06:14:16 +000095 * xmlUpgradeOldNs:
96 * @doc: a document pointer
97 *
98 * Upgrade old style Namespaces (PI) and move them to the root of the document.
Daniel Veillard260a68f1998-08-13 03:39:55 +000099 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000100void
101xmlUpgradeOldNs(xmlDocPtr doc) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000102 xmlNsPtr cur;
103
104 if ((doc == NULL) || (doc->oldNs == NULL)) return;
Daniel Veillardcf461992000-03-14 18:30:20 +0000105 if (doc->children == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000106#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000107 fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000108#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000109 return;
110 }
111
112 cur = doc->oldNs;
113 while (cur->next != NULL) {
114 cur->type = XML_LOCAL_NAMESPACE;
115 cur = cur->next;
116 }
117 cur->type = XML_LOCAL_NAMESPACE;
Daniel Veillardcf461992000-03-14 18:30:20 +0000118 cur->next = doc->children->nsDef;
119 doc->children->nsDef = doc->oldNs;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000120 doc->oldNs = NULL;
121}
122
Daniel Veillard97b58771998-10-20 06:14:16 +0000123/**
124 * xmlNewNs:
125 * @node: the element carrying the namespace
126 * @href: the URI associated
127 * @prefix: the prefix for the namespace
128 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000129 * Creation of a new Namespace. This function will refuse to create
130 * a namespace with a similar prefix than an existing one present on this
131 * node.
Daniel Veillarde0854c32000-08-27 21:12:29 +0000132 * We use href==NULL in the case of an element creation where the namespace
133 * was not defined.
Daniel Veillard686d6b62000-01-03 11:08:02 +0000134 * Returns returns a new namespace pointer or NULL
Daniel Veillard260a68f1998-08-13 03:39:55 +0000135 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000136xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000137xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000138 xmlNsPtr cur;
139
Daniel Veillard260a68f1998-08-13 03:39:55 +0000140 /*
Daniel Veillardcf461992000-03-14 18:30:20 +0000141 * Allocate a new Namespace and fill the fields.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000142 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000143 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000144 if (cur == NULL) {
145 fprintf(stderr, "xmlNewNs : malloc failed\n");
146 return(NULL);
147 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000148 memset(cur, 0, sizeof(xmlNs));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000149 cur->type = XML_LOCAL_NAMESPACE;
Daniel Veillardcf461992000-03-14 18:30:20 +0000150
Daniel Veillard260a68f1998-08-13 03:39:55 +0000151 if (href != NULL)
152 cur->href = xmlStrdup(href);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000153 if (prefix != NULL)
154 cur->prefix = xmlStrdup(prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000155
156 /*
157 * Add it at the end to preserve parsing order ...
Daniel Veillard686d6b62000-01-03 11:08:02 +0000158 * and checks for existing use of the prefix
Daniel Veillard260a68f1998-08-13 03:39:55 +0000159 */
Daniel Veillard260a68f1998-08-13 03:39:55 +0000160 if (node != NULL) {
161 if (node->nsDef == NULL) {
162 node->nsDef = cur;
163 } else {
164 xmlNsPtr prev = node->nsDef;
165
Daniel Veillard0142b842000-01-14 14:45:24 +0000166 if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
Daniel Veillard8b5dd832000-10-01 20:28:44 +0000167 (xmlStrEqual(prev->prefix, cur->prefix))) {
Daniel Veillard0142b842000-01-14 14:45:24 +0000168 xmlFreeNs(cur);
169 return(NULL);
170 }
Daniel Veillard686d6b62000-01-03 11:08:02 +0000171 while (prev->next != NULL) {
Daniel Veillard0142b842000-01-14 14:45:24 +0000172 prev = prev->next;
Daniel Veillard686d6b62000-01-03 11:08:02 +0000173 if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
Daniel Veillard8b5dd832000-10-01 20:28:44 +0000174 (xmlStrEqual(prev->prefix, cur->prefix))) {
Daniel Veillard686d6b62000-01-03 11:08:02 +0000175 xmlFreeNs(cur);
176 return(NULL);
177 }
Daniel Veillard686d6b62000-01-03 11:08:02 +0000178 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000179 prev->next = cur;
180 }
181 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000182 return(cur);
183}
184
Daniel Veillard97b58771998-10-20 06:14:16 +0000185/**
186 * xmlNewGlobalNs:
187 * @doc: the document carrying the namespace
188 * @href: the URI associated
189 * @prefix: the prefix for the namespace
190 *
Daniel Veillard686d6b62000-01-03 11:08:02 +0000191 * Creation of a Namespace, the old way using PI and without scoping
192 * DEPRECATED !!!
Daniel Veillard0142b842000-01-14 14:45:24 +0000193 * It now create a namespace on the root element of the document if found.
Daniel Veillard686d6b62000-01-03 11:08:02 +0000194 * Returns NULL this functionnality had been removed
Daniel Veillard260a68f1998-08-13 03:39:55 +0000195 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000196xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000197xmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) {
Daniel Veillard0142b842000-01-14 14:45:24 +0000198 xmlNodePtr root;
199
200 xmlNsPtr cur;
201
202 root = xmlDocGetRootElement(doc);
203 if (root != NULL)
204 return(xmlNewNs(root, href, prefix));
205
206 /*
207 * if there is no root element yet, create an old Namespace type
208 * and it will be moved to the root at save time.
209 */
210 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
211 if (cur == NULL) {
212 fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
213 return(NULL);
214 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000215 memset(cur, 0, sizeof(xmlNs));
Daniel Veillard0142b842000-01-14 14:45:24 +0000216 cur->type = XML_GLOBAL_NAMESPACE;
Daniel Veillardcf461992000-03-14 18:30:20 +0000217
Daniel Veillard0142b842000-01-14 14:45:24 +0000218 if (href != NULL)
219 cur->href = xmlStrdup(href);
Daniel Veillard0142b842000-01-14 14:45:24 +0000220 if (prefix != NULL)
221 cur->prefix = xmlStrdup(prefix);
Daniel Veillard0142b842000-01-14 14:45:24 +0000222
223 /*
224 * Add it at the end to preserve parsing order ...
225 */
Daniel Veillard0142b842000-01-14 14:45:24 +0000226 if (doc != NULL) {
227 if (doc->oldNs == NULL) {
228 doc->oldNs = cur;
229 } else {
230 xmlNsPtr prev = doc->oldNs;
231
232 while (prev->next != NULL) prev = prev->next;
233 prev->next = cur;
234 }
235 }
236
237 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000238}
239
Daniel Veillard97b58771998-10-20 06:14:16 +0000240/**
241 * xmlSetNs:
242 * @node: a node in the document
243 * @ns: a namespace pointer
244 *
245 * Associate a namespace to a node, a posteriori.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000246 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000247void
248xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000249 if (node == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000250#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000251 fprintf(stderr, "xmlSetNs: node == NULL\n");
Daniel Veillardcf461992000-03-14 18:30:20 +0000252#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000253 return;
254 }
255 node->ns = ns;
256}
257
Daniel Veillard97b58771998-10-20 06:14:16 +0000258/**
259 * xmlFreeNs:
260 * @cur: the namespace pointer
261 *
262 * Free up the structures associated to a namespace
Daniel Veillard260a68f1998-08-13 03:39:55 +0000263 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000264void
265xmlFreeNs(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000266 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000267#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000268 fprintf(stderr, "xmlFreeNs : ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000269#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000270 return;
271 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000272 if (cur->href != NULL) xmlFree((char *) cur->href);
273 if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000274 memset(cur, -1, sizeof(xmlNs));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000275 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000276}
277
Daniel Veillard97b58771998-10-20 06:14:16 +0000278/**
279 * xmlFreeNsList:
280 * @cur: the first namespace pointer
281 *
282 * Free up all the structures associated to the chained namespaces.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000283 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000284void
285xmlFreeNsList(xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000286 xmlNsPtr next;
287 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000288#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000289 fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000290#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000291 return;
292 }
293 while (cur != NULL) {
294 next = cur->next;
295 xmlFreeNs(cur);
296 cur = next;
297 }
298}
299
Daniel Veillard97b58771998-10-20 06:14:16 +0000300/**
301 * xmlNewDtd:
302 * @doc: the document pointer
303 * @name: the DTD name
304 * @ExternalID: the external ID
305 * @SystemID: the system ID
306 *
Daniel Veillardcf461992000-03-14 18:30:20 +0000307 * Creation of a new DTD for the external subset. To create an
308 * internal subset, use xmlCreateIntSubset().
309 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000310 * Returns a pointer to the new DTD structure
Daniel Veillard260a68f1998-08-13 03:39:55 +0000311 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000312xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000313xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
314 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000315 xmlDtdPtr cur;
316
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000317 if ((doc != NULL) && (doc->extSubset != NULL)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000318#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000319 fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000320 /* !!! */ (char *) name, doc->name,
321 /* !!! */ (char *)doc->extSubset->name);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000322#endif
323 return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000324 }
325
326 /*
327 * Allocate a new DTD and fill the fields.
328 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000329 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000330 if (cur == NULL) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000331 fprintf(stderr, "xmlNewDtd : malloc failed\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +0000332 return(NULL);
333 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000334 memset(cur, 0 , sizeof(xmlDtd));
335 cur->type = XML_DTD_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000336
337 if (name != NULL)
338 cur->name = xmlStrdup(name);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000339 if (ExternalID != NULL)
340 cur->ExternalID = xmlStrdup(ExternalID);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000341 if (SystemID != NULL)
342 cur->SystemID = xmlStrdup(SystemID);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000343 if (doc != NULL)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000344 doc->extSubset = cur;
Daniel Veillardcf461992000-03-14 18:30:20 +0000345 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000346
347 return(cur);
348}
349
350/**
Daniel Veillardcf461992000-03-14 18:30:20 +0000351 * xmlGetIntSubset:
352 * @doc: the document pointer
353 *
354 * Get the internal subset of a document
355 * Returns a pointer to the DTD structure or NULL if not found
356 */
357
358xmlDtdPtr
359xmlGetIntSubset(xmlDocPtr doc) {
360 xmlNodePtr cur;
361
362 if (doc == NULL)
363 return(NULL);
364 cur = doc->children;
365 while (cur != NULL) {
366 if (cur->type == XML_DTD_NODE)
367 return((xmlDtdPtr) cur);
368 cur = cur->next;
369 }
370 return((xmlDtdPtr) doc->intSubset);
371}
372
373/**
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000374 * xmlCreateIntSubset:
375 * @doc: the document pointer
376 * @name: the DTD name
377 * @ExternalID: the external ID
378 * @SystemID: the system ID
379 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000380 * Create the internal subset of a document
381 * Returns a pointer to the new DTD structure
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000382 */
383xmlDtdPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000384xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
385 const xmlChar *ExternalID, const xmlChar *SystemID) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000386 xmlDtdPtr cur;
387
Daniel Veillardcf461992000-03-14 18:30:20 +0000388 if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000389#ifdef DEBUG_TREE
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000390 fprintf(stderr,
391 "xmlCreateIntSubset(): document %s already have an internal subset\n",
392 doc->name);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000393#endif
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000394 return(NULL);
395 }
396
397 /*
398 * Allocate a new DTD and fill the fields.
399 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000400 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000401 if (cur == NULL) {
402 fprintf(stderr, "xmlNewDtd : malloc failed\n");
403 return(NULL);
404 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000405 memset(cur, 0, sizeof(xmlDtd));
406 cur->type = XML_DTD_NODE;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000407
408 if (name != NULL)
409 cur->name = xmlStrdup(name);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000410 if (ExternalID != NULL)
411 cur->ExternalID = xmlStrdup(ExternalID);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000412 if (SystemID != NULL)
413 cur->SystemID = xmlStrdup(SystemID);
Daniel Veillardcf461992000-03-14 18:30:20 +0000414 if (doc != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000415 doc->intSubset = cur;
Daniel Veillardcf461992000-03-14 18:30:20 +0000416 cur->parent = doc;
417 cur->doc = doc;
418 if (doc->children == NULL) {
419 doc->children = (xmlNodePtr) cur;
420 doc->last = (xmlNodePtr) cur;
421 } else {
422 xmlNodePtr prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000423
Daniel Veillardb8f25c92000-08-19 19:52:36 +0000424 if (doc->type == XML_HTML_DOCUMENT_NODE) {
425 prev = doc->children;
426 prev->prev = (xmlNodePtr) cur;
427 cur->next = prev;
428 doc->children = (xmlNodePtr) cur;
429 } else {
430 prev = doc->last;
431 prev->next = (xmlNodePtr) cur;
432 cur->prev = prev;
433 doc->last = (xmlNodePtr) cur;
434 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000435 }
436 }
Daniel Veillard260a68f1998-08-13 03:39:55 +0000437 return(cur);
438}
439
Daniel Veillard97b58771998-10-20 06:14:16 +0000440/**
441 * xmlFreeDtd:
442 * @cur: the DTD structure to free up
443 *
444 * Free a DTD structure.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000445 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000446void
447xmlFreeDtd(xmlDtdPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000448 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000449#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000450 fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000451#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000452 return;
453 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000454 if (cur->children != NULL) {
455 xmlNodePtr next, c = cur->children;
456
457 /*
458 * Cleanup all the DTD comments they are not in the Dtd
459 * indexes.
460 */
461 while (c != NULL) {
462 next = c->next;
463 if (c->type == XML_COMMENT_NODE) {
464 xmlUnlinkNode(c);
465 xmlFreeNode(c);
466 }
467 c = next;
468 }
469 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000470 if (cur->name != NULL) xmlFree((char *) cur->name);
471 if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
472 if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
Daniel Veillardcf461992000-03-14 18:30:20 +0000473 /* TODO !!! */
Daniel Veillard1e346af1999-02-22 10:33:01 +0000474 if (cur->notations != NULL)
475 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
Daniel Veillardcf461992000-03-14 18:30:20 +0000476
Daniel Veillard260a68f1998-08-13 03:39:55 +0000477 if (cur->elements != NULL)
Daniel Veillard3b9def11999-01-31 22:15:06 +0000478 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
Daniel Veillard1e346af1999-02-22 10:33:01 +0000479 if (cur->attributes != NULL)
480 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000481 if (cur->entities != NULL)
482 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
Daniel Veillardcf461992000-03-14 18:30:20 +0000483
Daniel Veillard260a68f1998-08-13 03:39:55 +0000484 memset(cur, -1, sizeof(xmlDtd));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000485 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000486}
487
Daniel Veillard97b58771998-10-20 06:14:16 +0000488/**
489 * xmlNewDoc:
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000490 * @version: xmlChar string giving the version of XML "1.0"
Daniel Veillard97b58771998-10-20 06:14:16 +0000491 *
Daniel Veillard1e346af1999-02-22 10:33:01 +0000492 * Returns a new document
Daniel Veillard260a68f1998-08-13 03:39:55 +0000493 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000494xmlDocPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000495xmlNewDoc(const xmlChar *version) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000496 xmlDocPtr cur;
497
Daniel Veillard7eda8452000-10-14 23:38:43 +0000498 if (version == NULL)
499 version = (const xmlChar *) "1.0";
Daniel Veillard260a68f1998-08-13 03:39:55 +0000500
501 /*
502 * Allocate a new document and fill the fields.
503 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000504 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000505 if (cur == NULL) {
506 fprintf(stderr, "xmlNewDoc : malloc failed\n");
507 return(NULL);
508 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000509 memset(cur, 0, sizeof(xmlDoc));
Daniel Veillard33942841998-10-18 19:12:41 +0000510 cur->type = XML_DOCUMENT_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +0000511
Daniel Veillard260a68f1998-08-13 03:39:55 +0000512 cur->version = xmlStrdup(version);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000513 cur->standalone = -1;
Daniel Veillard11a48ec1999-11-23 10:40:46 +0000514 cur->compression = -1; /* not initialized */
Daniel Veillardcf461992000-03-14 18:30:20 +0000515 cur->doc = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000516 return(cur);
517}
518
Daniel Veillard97b58771998-10-20 06:14:16 +0000519/**
520 * xmlFreeDoc:
521 * @cur: pointer to the document
522 * @:
523 *
524 * Free up all the structures used by a document, tree included.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000525 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000526void
527xmlFreeDoc(xmlDocPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000528 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000529#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000530 fprintf(stderr, "xmlFreeDoc : document == NULL\n");
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000531#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000532 return;
533 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000534 if (cur->version != NULL) xmlFree((char *) cur->version);
535 if (cur->name != NULL) xmlFree((char *) cur->name);
536 if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
Daniel Veillardcf461992000-03-14 18:30:20 +0000537 if (cur->children != NULL) xmlFreeNodeList(cur->children);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +0000538 if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
539 if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +0000540 if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
Daniel Veillardb96e6431999-08-29 21:02:19 +0000541 if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
Daniel Veillardc08a2c61999-09-08 21:35:25 +0000542 if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
Daniel Veillardcf461992000-03-14 18:30:20 +0000543 if (cur->URL != NULL) xmlFree((char *) cur->URL);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000544 memset(cur, -1, sizeof(xmlDoc));
Daniel Veillard6454aec1999-09-02 22:04:43 +0000545 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +0000546}
547
Daniel Veillard97b58771998-10-20 06:14:16 +0000548/**
Daniel Veillard16253641998-10-28 22:58:05 +0000549 * xmlStringLenGetNodeList:
550 * @doc: the document
551 * @value: the value of the text
Daniel Veillard1e346af1999-02-22 10:33:01 +0000552 * @len: the length of the string value
Daniel Veillard16253641998-10-28 22:58:05 +0000553 *
554 * Parse the value string and build the node list associated. Should
555 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000556 * Returns a pointer to the first child
Daniel Veillard16253641998-10-28 22:58:05 +0000557 */
558xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000559xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
Daniel Veillard16253641998-10-28 22:58:05 +0000560 xmlNodePtr ret = NULL, last = NULL;
561 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000562 xmlChar *val;
563 const xmlChar *cur = value;
564 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000565 xmlEntityPtr ent;
Daniel Veillard16253641998-10-28 22:58:05 +0000566
567 if (value == NULL) return(NULL);
568
569 q = cur;
570 while ((*cur != 0) && (cur - value < len)) {
571 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000572 /*
573 * Save the current text.
574 */
Daniel Veillard16253641998-10-28 22:58:05 +0000575 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000576 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
577 xmlNodeAddContentLen(last, q, cur - q);
578 } else {
579 node = xmlNewDocTextLen(doc, q, cur - q);
580 if (node == NULL) return(ret);
581 if (last == NULL)
582 last = ret = node;
583 else {
584 last->next = node;
585 node->prev = last;
586 last = node;
587 }
Daniel Veillard16253641998-10-28 22:58:05 +0000588 }
589 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000590 /*
591 * Read the entity string
592 */
Daniel Veillard16253641998-10-28 22:58:05 +0000593 cur++;
594 q = cur;
595 while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
596 if ((*cur == 0) || (cur - value >= len)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000597#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +0000598 fprintf(stderr,
Daniel Veillard011b63c1999-06-02 17:44:04 +0000599 "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000600#endif
Daniel Veillard16253641998-10-28 22:58:05 +0000601 return(ret);
602 }
603 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000604 /*
605 * Predefined entities don't generate nodes
606 */
Daniel Veillard16253641998-10-28 22:58:05 +0000607 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000608 ent = xmlGetDocEntity(doc, val);
609 if ((ent != NULL) &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000610 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000611 if (last == NULL) {
612 node = xmlNewDocText(doc, ent->content);
613 last = ret = node;
614 } else
615 xmlNodeAddContent(last, ent->content);
616
617 } else {
618 /*
619 * Create a new REFERENCE_REF node
620 */
621 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000622 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000623 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000624 return(ret);
625 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000626 if (last == NULL)
627 last = ret = node;
628 else {
629 last->next = node;
630 node->prev = last;
631 last = node;
632 }
Daniel Veillard16253641998-10-28 22:58:05 +0000633 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000634 xmlFree(val);
Daniel Veillard16253641998-10-28 22:58:05 +0000635 }
636 cur++;
637 q = cur;
638 } else
639 cur++;
640 }
641 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000642 /*
643 * Handle the last piece of text.
644 */
645 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
646 xmlNodeAddContentLen(last, q, cur - q);
647 } else {
648 node = xmlNewDocTextLen(doc, q, cur - q);
649 if (node == NULL) return(ret);
650 if (last == NULL)
651 last = ret = node;
652 else {
653 last->next = node;
654 node->prev = last;
655 last = node;
656 }
Daniel Veillard16253641998-10-28 22:58:05 +0000657 }
658 }
659 return(ret);
660}
661
662/**
Daniel Veillardccb09631998-10-27 06:21:04 +0000663 * xmlStringGetNodeList:
664 * @doc: the document
665 * @value: the value of the attribute
666 *
667 * Parse the value string and build the node list associated. Should
668 * produce a flat tree with only TEXTs and ENTITY_REFs.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000669 * Returns a pointer to the first child
Daniel Veillardccb09631998-10-27 06:21:04 +0000670 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000671xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000672xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000673 xmlNodePtr ret = NULL, last = NULL;
674 xmlNodePtr node;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000675 xmlChar *val;
676 const xmlChar *cur = value;
677 const xmlChar *q;
Daniel Veillard25940b71998-10-29 05:51:30 +0000678 xmlEntityPtr ent;
Daniel Veillardccb09631998-10-27 06:21:04 +0000679
680 if (value == NULL) return(NULL);
681
682 q = cur;
683 while (*cur != 0) {
684 if (*cur == '&') {
Daniel Veillard25940b71998-10-29 05:51:30 +0000685 /*
686 * Save the current text.
687 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000688 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000689 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
690 xmlNodeAddContentLen(last, q, cur - q);
691 } else {
692 node = xmlNewDocTextLen(doc, q, cur - q);
693 if (node == NULL) return(ret);
694 if (last == NULL)
695 last = ret = node;
696 else {
697 last->next = node;
698 node->prev = last;
699 last = node;
700 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000701 }
702 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000703 /*
704 * Read the entity string
705 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000706 cur++;
707 q = cur;
708 while ((*cur != 0) && (*cur != ';')) cur++;
709 if (*cur == 0) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000710#ifdef DEBUG_TREE
Daniel Veillardccb09631998-10-27 06:21:04 +0000711 fprintf(stderr,
712 "xmlStringGetNodeList: unterminated entity %30s\n", q);
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000713#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000714 return(ret);
715 }
716 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000717 /*
718 * Predefined entities don't generate nodes
719 */
Daniel Veillardccb09631998-10-27 06:21:04 +0000720 val = xmlStrndup(q, cur - q);
Daniel Veillard25940b71998-10-29 05:51:30 +0000721 ent = xmlGetDocEntity(doc, val);
722 if ((ent != NULL) &&
Daniel Veillardcf461992000-03-14 18:30:20 +0000723 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000724 if (last == NULL) {
725 node = xmlNewDocText(doc, ent->content);
726 last = ret = node;
727 } else
728 xmlNodeAddContent(last, ent->content);
729
730 } else {
731 /*
732 * Create a new REFERENCE_REF node
733 */
Daniel Veillard25940b71998-10-29 05:51:30 +0000734 node = xmlNewReference(doc, val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000735 if (node == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +0000736 if (val != NULL) xmlFree(val);
Daniel Veillard242590e1998-11-13 18:04:35 +0000737 return(ret);
738 }
Daniel Veillard25940b71998-10-29 05:51:30 +0000739 if (last == NULL)
740 last = ret = node;
741 else {
742 last->next = node;
743 node->prev = last;
744 last = node;
745 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000746 }
Daniel Veillard6454aec1999-09-02 22:04:43 +0000747 xmlFree(val);
Daniel Veillardccb09631998-10-27 06:21:04 +0000748 }
749 cur++;
750 q = cur;
751 } else
752 cur++;
753 }
754 if (cur != q) {
Daniel Veillard25940b71998-10-29 05:51:30 +0000755 /*
756 * Handle the last piece of text.
757 */
758 if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
759 xmlNodeAddContentLen(last, q, cur - q);
760 } else {
761 node = xmlNewDocTextLen(doc, q, cur - q);
762 if (node == NULL) return(ret);
763 if (last == NULL)
764 last = ret = node;
765 else {
766 last->next = node;
767 node->prev = last;
768 last = node;
769 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000770 }
771 }
772 return(ret);
773}
774
775/**
776 * xmlNodeListGetString:
777 * @doc: the document
778 * @list: a Node list
779 * @inLine: should we replace entity contents or show their external form
780 *
781 * Returns the string equivalent to the text contained in the Node list
782 * made of TEXTs and ENTITY_REFs
Daniel Veillard1e346af1999-02-22 10:33:01 +0000783 * Returns a pointer to the string copy, the calller must free it.
Daniel Veillardccb09631998-10-27 06:21:04 +0000784 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000785xmlChar *
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000786xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
Daniel Veillardccb09631998-10-27 06:21:04 +0000787 xmlNodePtr node = list;
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000788 xmlChar *ret = NULL;
Daniel Veillardccb09631998-10-27 06:21:04 +0000789 xmlEntityPtr ent;
790
791 if (list == NULL) return(NULL);
792
793 while (node != NULL) {
Daniel Veillard87b95392000-08-12 21:12:04 +0000794 if ((node->type == XML_TEXT_NODE) ||
795 (node->type == XML_CDATA_SECTION_NODE)) {
Daniel Veillard71b656e2000-01-05 14:46:17 +0000796 if (inLine) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000797#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000798 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000799#else
800 ret = xmlStrcat(ret, xmlBufferContent(node->content));
801#endif
802 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000803 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +0000804
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000805#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +0000806 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000807#else
808 buffer = xmlEncodeEntitiesReentrant(doc,
809 xmlBufferContent(node->content));
810#endif
Daniel Veillard14fff061999-06-22 21:49:07 +0000811 if (buffer != NULL) {
812 ret = xmlStrcat(ret, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +0000813 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +0000814 }
815 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000816 } else if (node->type == XML_ENTITY_REF_NODE) {
817 if (inLine) {
818 ent = xmlGetDocEntity(doc, node->name);
819 if (ent != NULL)
820 ret = xmlStrcat(ret, ent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000821 else {
822#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +0000823 ret = xmlStrcat(ret, node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +0000824#else
825 ret = xmlStrcat(ret, xmlBufferContent(node->content));
826#endif
827 }
Daniel Veillardccb09631998-10-27 06:21:04 +0000828 } else {
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000829 xmlChar buf[2];
Daniel Veillardccb09631998-10-27 06:21:04 +0000830 buf[0] = '&'; buf[1] = 0;
831 ret = xmlStrncat(ret, buf, 1);
832 ret = xmlStrcat(ret, node->name);
833 buf[0] = ';'; buf[1] = 0;
834 ret = xmlStrncat(ret, buf, 1);
835 }
836 }
837#if 0
838 else {
839 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
840 node->type);
841 }
842#endif
843 node = node->next;
844 }
845 return(ret);
846}
847
848/**
Daniel Veillardbe803962000-06-28 23:40:59 +0000849 * xmlNodeListGetRawString:
850 * @doc: the document
851 * @list: a Node list
852 * @inLine: should we replace entity contents or show their external form
853 *
854 * Returns the string equivalent to the text contained in the Node list
855 * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
856 * this function doesn't do any character encoding handling.
857 *
858 * Returns a pointer to the string copy, the calller must free it.
859 */
860xmlChar *
861xmlNodeListGetRawString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
862 xmlNodePtr node = list;
863 xmlChar *ret = NULL;
864 xmlEntityPtr ent;
865
866 if (list == NULL) return(NULL);
867
868 while (node != NULL) {
869 if (node->type == XML_TEXT_NODE) {
870 if (inLine) {
871#ifndef XML_USE_BUFFER_CONTENT
872 ret = xmlStrcat(ret, node->content);
873#else
874 ret = xmlStrcat(ret, xmlBufferContent(node->content));
875#endif
876 } else {
877 xmlChar *buffer;
878
879#ifndef XML_USE_BUFFER_CONTENT
880 buffer = xmlEncodeSpecialChars(doc, node->content);
881#else
882 buffer = xmlEncodeSpecialChars(doc,
883 xmlBufferContent(node->content));
884#endif
885 if (buffer != NULL) {
886 ret = xmlStrcat(ret, buffer);
887 xmlFree(buffer);
888 }
889 }
890 } else if (node->type == XML_ENTITY_REF_NODE) {
891 if (inLine) {
892 ent = xmlGetDocEntity(doc, node->name);
893 if (ent != NULL)
894 ret = xmlStrcat(ret, ent->content);
895 else {
896#ifndef XML_USE_BUFFER_CONTENT
897 ret = xmlStrcat(ret, node->content);
898#else
899 ret = xmlStrcat(ret, xmlBufferContent(node->content));
900#endif
901 }
902 } else {
903 xmlChar buf[2];
904 buf[0] = '&'; buf[1] = 0;
905 ret = xmlStrncat(ret, buf, 1);
906 ret = xmlStrcat(ret, node->name);
907 buf[0] = ';'; buf[1] = 0;
908 ret = xmlStrncat(ret, buf, 1);
909 }
910 }
911#if 0
912 else {
913 fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
914 node->type);
915 }
916#endif
917 node = node->next;
918 }
919 return(ret);
920}
921
922/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000923 * xmlNewProp:
924 * @node: the holding node
925 * @name: the name of the attribute
926 * @value: the value of the attribute
927 *
928 * Create a new property carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +0000929 * Returns a pointer to the attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +0000930 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +0000931xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000932xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +0000933 xmlAttrPtr cur;
934
935 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000936#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +0000937 fprintf(stderr, "xmlNewProp : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +0000938#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000939 return(NULL);
940 }
941
942 /*
943 * Allocate a new property and fill the fields.
944 */
Daniel Veillard6454aec1999-09-02 22:04:43 +0000945 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillard260a68f1998-08-13 03:39:55 +0000946 if (cur == NULL) {
947 fprintf(stderr, "xmlNewProp : malloc failed\n");
948 return(NULL);
949 }
Daniel Veillardcf461992000-03-14 18:30:20 +0000950 memset(cur, 0, sizeof(xmlAttr));
Daniel Veillard33942841998-10-18 19:12:41 +0000951 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +0000952
953 cur->parent = node;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000954 cur->name = xmlStrdup(name);
Daniel Veillard51e3b151999-11-12 17:02:31 +0000955 if (value != NULL) {
956 xmlChar *buffer;
Daniel Veillardcf461992000-03-14 18:30:20 +0000957 xmlNodePtr tmp;
958
Daniel Veillard51e3b151999-11-12 17:02:31 +0000959 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
Daniel Veillardcf461992000-03-14 18:30:20 +0000960 cur->children = xmlStringGetNodeList(node->doc, buffer);
961 tmp = cur->children;
962 while (tmp != NULL) {
963 tmp->parent = (xmlNodePtr) cur;
964 if (tmp->next == NULL)
965 cur->last = tmp;
966 tmp = tmp->next;
967 }
Daniel Veillard51e3b151999-11-12 17:02:31 +0000968 xmlFree(buffer);
969 }
Daniel Veillardb96e6431999-08-29 21:02:19 +0000970
971 /*
972 * Add it at the end to preserve parsing order ...
973 */
Daniel Veillardb96e6431999-08-29 21:02:19 +0000974 if (node != NULL) {
975 if (node->properties == NULL) {
976 node->properties = cur;
977 } else {
978 xmlAttrPtr prev = node->properties;
979
980 while (prev->next != NULL) prev = prev->next;
981 prev->next = cur;
Daniel Veillardcf461992000-03-14 18:30:20 +0000982 cur->prev = prev;
Daniel Veillardb96e6431999-08-29 21:02:19 +0000983 }
984 }
985 return(cur);
986}
987
988/**
989 * xmlNewNsProp:
990 * @node: the holding node
991 * @ns: the namespace
992 * @name: the name of the attribute
993 * @value: the value of the attribute
994 *
995 * Create a new property tagged with a namespace and carried by a node.
996 * Returns a pointer to the attribute
997 */
998xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +0000999xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
1000 const xmlChar *value) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001001 xmlAttrPtr cur;
1002
1003 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001004#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001005 fprintf(stderr, "xmlNewProp : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001006#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001007 return(NULL);
1008 }
1009
1010 /*
1011 * Allocate a new property and fill the fields.
1012 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001013 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00001014 if (cur == NULL) {
1015 fprintf(stderr, "xmlNewProp : malloc failed\n");
1016 return(NULL);
1017 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001018 memset(cur, 0, sizeof(xmlAttr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00001019 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001020
1021 cur->parent = node;
1022 if (node != NULL)
1023 cur->doc = node->doc;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001024 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001025 cur->name = xmlStrdup(name);
Daniel Veillardcf461992000-03-14 18:30:20 +00001026 if (value != NULL) {
1027 xmlChar *buffer;
1028 xmlNodePtr tmp;
1029
1030 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
1031 cur->children = xmlStringGetNodeList(node->doc, buffer);
1032 tmp = cur->children;
1033 while (tmp != NULL) {
1034 tmp->parent = (xmlNodePtr) cur;
1035 if (tmp->next == NULL)
1036 cur->last = tmp;
1037 tmp = tmp->next;
1038 }
1039 xmlFree(buffer);
1040 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001041
1042 /*
1043 * Add it at the end to preserve parsing order ...
1044 */
Daniel Veillard260a68f1998-08-13 03:39:55 +00001045 if (node != NULL) {
1046 if (node->properties == NULL) {
1047 node->properties = cur;
1048 } else {
1049 xmlAttrPtr prev = node->properties;
1050
1051 while (prev->next != NULL) prev = prev->next;
1052 prev->next = cur;
Daniel Veillardcf461992000-03-14 18:30:20 +00001053 cur->prev = prev;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001054 }
1055 }
1056 return(cur);
1057}
1058
Daniel Veillard97b58771998-10-20 06:14:16 +00001059/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001060 * xmlNewDocProp:
1061 * @doc: the document
1062 * @name: the name of the attribute
1063 * @value: the value of the attribute
1064 *
1065 * Create a new property carried by a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001066 * Returns a pointer to the attribute
Daniel Veillardccb09631998-10-27 06:21:04 +00001067 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001068xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001069xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001070 xmlAttrPtr cur;
1071
1072 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001073#ifdef DEBUG_TREE
Daniel Veillardccb09631998-10-27 06:21:04 +00001074 fprintf(stderr, "xmlNewProp : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001075#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00001076 return(NULL);
1077 }
1078
1079 /*
1080 * Allocate a new property and fill the fields.
1081 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001082 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +00001083 if (cur == NULL) {
1084 fprintf(stderr, "xmlNewProp : malloc failed\n");
1085 return(NULL);
1086 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001087 memset(cur, 0, sizeof(xmlAttr));
Daniel Veillardccb09631998-10-27 06:21:04 +00001088 cur->type = XML_ATTRIBUTE_NODE;
Daniel Veillardccb09631998-10-27 06:21:04 +00001089
Daniel Veillardcf461992000-03-14 18:30:20 +00001090 cur->name = xmlStrdup(name);
1091 cur->doc = doc;
1092 if (value != NULL)
1093 cur->children = xmlStringGetNodeList(doc, value);
Daniel Veillardccb09631998-10-27 06:21:04 +00001094 return(cur);
1095}
1096
1097/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001098 * xmlFreePropList:
1099 * @cur: the first property in the list
1100 *
Daniel Veillardcf461992000-03-14 18:30:20 +00001101 * Free a property and all its siblings, all the children are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001102 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001103void
1104xmlFreePropList(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001105 xmlAttrPtr next;
1106 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001107#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001108 fprintf(stderr, "xmlFreePropList : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001109#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001110 return;
1111 }
1112 while (cur != NULL) {
1113 next = cur->next;
1114 xmlFreeProp(cur);
1115 cur = next;
1116 }
1117}
1118
Daniel Veillard97b58771998-10-20 06:14:16 +00001119/**
1120 * xmlFreeProp:
Daniel Veillard686d6b62000-01-03 11:08:02 +00001121 * @cur: an attribute
Daniel Veillard97b58771998-10-20 06:14:16 +00001122 *
Daniel Veillard686d6b62000-01-03 11:08:02 +00001123 * Free one attribute, all the content is freed too
Daniel Veillard260a68f1998-08-13 03:39:55 +00001124 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001125void
1126xmlFreeProp(xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001127 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001128#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001129 fprintf(stderr, "xmlFreeProp : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001130#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001131 return;
1132 }
Daniel Veillard71b656e2000-01-05 14:46:17 +00001133 /* Check for ID removal -> leading to invalid references ! */
Daniel Veillardcf461992000-03-14 18:30:20 +00001134 if ((cur->parent != NULL) &&
1135 (xmlIsID(cur->parent->doc, cur->parent, cur)))
1136 xmlRemoveID(cur->parent->doc, cur);
Daniel Veillard6454aec1999-09-02 22:04:43 +00001137 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillardcf461992000-03-14 18:30:20 +00001138 if (cur->children != NULL) xmlFreeNodeList(cur->children);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001139 memset(cur, -1, sizeof(xmlAttr));
Daniel Veillard6454aec1999-09-02 22:04:43 +00001140 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001141}
1142
Daniel Veillard97b58771998-10-20 06:14:16 +00001143/**
Daniel Veillard686d6b62000-01-03 11:08:02 +00001144 * xmlRemoveProp:
1145 * @cur: an attribute
1146 *
1147 * Unlink and free one attribute, all the content is freed too
1148 * Note this doesn't work for namespace definition attributes
1149 *
1150 * Returns 0 if success and -1 in case of error.
1151 */
1152int
1153xmlRemoveProp(xmlAttrPtr cur) {
1154 xmlAttrPtr tmp;
1155 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001156#ifdef DEBUG_TREE
Daniel Veillard686d6b62000-01-03 11:08:02 +00001157 fprintf(stderr, "xmlRemoveProp : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001158#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +00001159 return(-1);
1160 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001161 if (cur->parent == NULL) {
1162#ifdef DEBUG_TREE
1163 fprintf(stderr, "xmlRemoveProp : cur->parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001164#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +00001165 return(-1);
1166 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001167 tmp = cur->parent->properties;
Daniel Veillard686d6b62000-01-03 11:08:02 +00001168 if (tmp == cur) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001169 cur->parent->properties = cur->next;
Daniel Veillard686d6b62000-01-03 11:08:02 +00001170 xmlFreeProp(cur);
1171 return(0);
1172 }
1173 while (tmp != NULL) {
1174 if (tmp->next == cur) {
1175 tmp->next = cur->next;
Daniel Veillardcf461992000-03-14 18:30:20 +00001176 if (tmp->next != NULL)
1177 tmp->next->prev = tmp;
Daniel Veillard686d6b62000-01-03 11:08:02 +00001178 xmlFreeProp(cur);
1179 return(0);
1180 }
1181 tmp = tmp->next;
1182 }
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001183#ifdef DEBUG_TREE
Daniel Veillard686d6b62000-01-03 11:08:02 +00001184 fprintf(stderr, "xmlRemoveProp : attribute not owned by its node\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001185#endif
Daniel Veillard686d6b62000-01-03 11:08:02 +00001186 return(-1);
1187}
1188
1189/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001190 * xmlNewPI:
1191 * @name: the processing instruction name
1192 * @content: the PI content
1193 *
1194 * Creation of a processing instruction element.
1195 * Returns a pointer to the new node object.
1196 */
1197xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001198xmlNewPI(const xmlChar *name, const xmlChar *content) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00001199 xmlNodePtr cur;
1200
1201 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001202#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001203 fprintf(stderr, "xmlNewPI : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001204#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001205 return(NULL);
1206 }
1207
1208 /*
1209 * Allocate a new node and fill the fields.
1210 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001211 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +00001212 if (cur == NULL) {
1213 fprintf(stderr, "xmlNewPI : malloc failed\n");
1214 return(NULL);
1215 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001216 memset(cur, 0, sizeof(xmlNode));
Daniel Veillardb96e6431999-08-29 21:02:19 +00001217 cur->type = XML_PI_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001218
Daniel Veillardb96e6431999-08-29 21:02:19 +00001219 cur->name = xmlStrdup(name);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001220 if (content != NULL) {
1221#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00001222 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001223#else
1224 cur->content = xmlBufferCreateSize(0);
1225 xmlBufferSetAllocationScheme(cur->content,
1226 xmlGetBufferAllocationScheme());
1227 xmlBufferAdd(cur->content, content, -1);
1228#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001229 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00001230 return(cur);
1231}
1232
1233/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001234 * xmlNewNode:
1235 * @ns: namespace if any
1236 * @name: the node name
Daniel Veillard97b58771998-10-20 06:14:16 +00001237 *
Daniel Veillarde0854c32000-08-27 21:12:29 +00001238 * Creation of a new node element. @ns is optionnal (NULL).
1239 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001240 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001241 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001242xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001243xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001244 xmlNodePtr cur;
1245
1246 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001247#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001248 fprintf(stderr, "xmlNewNode : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001249#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001250 return(NULL);
1251 }
1252
1253 /*
1254 * Allocate a new node and fill the fields.
1255 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001256 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001257 if (cur == NULL) {
1258 fprintf(stderr, "xmlNewNode : malloc failed\n");
1259 return(NULL);
1260 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001261 memset(cur, 0, sizeof(xmlNode));
Daniel Veillard33942841998-10-18 19:12:41 +00001262 cur->type = XML_ELEMENT_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001263
Daniel Veillard260a68f1998-08-13 03:39:55 +00001264 cur->name = xmlStrdup(name);
1265 cur->ns = ns;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001266 return(cur);
1267}
1268
Daniel Veillard97b58771998-10-20 06:14:16 +00001269/**
1270 * xmlNewDocNode:
1271 * @doc: the document
1272 * @ns: namespace if any
1273 * @name: the node name
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001274 * @content: the XML text content if any
Daniel Veillard97b58771998-10-20 06:14:16 +00001275 *
1276 * Creation of a new node element within a document. @ns and @content
1277 * are optionnal (NULL).
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001278 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1279 * references, but XML special chars need to be escaped first by using
1280 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
1281 * need entities support.
1282 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001283 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001284 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001285xmlNodePtr
1286xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001287 const xmlChar *name, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001288 xmlNodePtr cur;
1289
Daniel Veillardccb09631998-10-27 06:21:04 +00001290 cur = xmlNewNode(ns, name);
1291 if (cur != NULL) {
1292 cur->doc = doc;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001293 if (content != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001294 cur->children = xmlStringGetNodeList(doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00001295 UPDATE_LAST_CHILD(cur)
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001296 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001297 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00001298 return(cur);
1299}
1300
1301
Daniel Veillard97b58771998-10-20 06:14:16 +00001302/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001303 * xmlNewDocRawNode:
1304 * @doc: the document
1305 * @ns: namespace if any
1306 * @name: the node name
1307 * @content: the text content if any
1308 *
1309 * Creation of a new node element within a document. @ns and @content
1310 * are optionnal (NULL).
1311 *
1312 * Returns a pointer to the new node object.
1313 */
1314xmlNodePtr
1315xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
1316 const xmlChar *name, const xmlChar *content) {
1317 xmlNodePtr cur;
1318
1319 cur = xmlNewNode(ns, name);
1320 if (cur != NULL) {
1321 cur->doc = doc;
1322 if (content != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00001323 cur->children = xmlNewDocText(doc, content);
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001324 UPDATE_LAST_CHILD(cur)
1325 }
1326 }
1327 return(cur);
1328}
1329
Daniel Veillard2eac5032000-01-09 21:08:56 +00001330/**
1331 * xmlNewDocFragment:
1332 * @doc: the document owning the fragment
1333 *
1334 * Creation of a new Fragment node.
1335 * Returns a pointer to the new node object.
1336 */
1337xmlNodePtr
1338xmlNewDocFragment(xmlDocPtr doc) {
1339 xmlNodePtr cur;
1340
1341 /*
1342 * Allocate a new DocumentFragment node and fill the fields.
1343 */
1344 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1345 if (cur == NULL) {
1346 fprintf(stderr, "xmlNewDocFragment : malloc failed\n");
1347 return(NULL);
1348 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001349 memset(cur, 0, sizeof(xmlNode));
Daniel Veillard2eac5032000-01-09 21:08:56 +00001350 cur->type = XML_DOCUMENT_FRAG_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001351
Daniel Veillard2eac5032000-01-09 21:08:56 +00001352 cur->doc = doc;
Daniel Veillard2eac5032000-01-09 21:08:56 +00001353 return(cur);
1354}
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001355
1356/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001357 * xmlNewText:
1358 * @content: the text content
1359 *
1360 * Creation of a new text node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001361 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001362 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001363xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001364xmlNewText(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001365 xmlNodePtr cur;
1366
1367 /*
1368 * Allocate a new node and fill the fields.
1369 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001370 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001371 if (cur == NULL) {
1372 fprintf(stderr, "xmlNewText : malloc failed\n");
1373 return(NULL);
1374 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001375 memset(cur, 0, sizeof(xmlNode));
1376 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001377
Daniel Veillard260a68f1998-08-13 03:39:55 +00001378 cur->name = xmlStrdup(xmlStringText);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001379 if (content != NULL) {
1380#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001381 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001382#else
1383 cur->content = xmlBufferCreateSize(0);
1384 xmlBufferSetAllocationScheme(cur->content,
1385 xmlGetBufferAllocationScheme());
1386 xmlBufferAdd(cur->content, content, -1);
1387#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001388 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001389 return(cur);
1390}
1391
Daniel Veillard97b58771998-10-20 06:14:16 +00001392/**
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001393 * xmlNewTextChild:
1394 * @parent: the parent node
1395 * @ns: a namespace if any
1396 * @name: the name of the child
1397 * @content: the text content of the child if any.
1398 *
Daniel Veillardcf461992000-03-14 18:30:20 +00001399 * Creation of a new child element, added at the end of @parent children list.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001400 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1401 * a child TEXT node will be created containing the string content.
1402 *
1403 * Returns a pointer to the new node object.
1404 */
1405xmlNodePtr
1406xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
1407 const xmlChar *name, const xmlChar *content) {
1408 xmlNodePtr cur, prev;
1409
1410 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001411#ifdef DEBUG_TREE
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001412 fprintf(stderr, "xmlNewTextChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001413#endif
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001414 return(NULL);
1415 }
1416
1417 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001418#ifdef DEBUG_TREE
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001419 fprintf(stderr, "xmlNewTextChild : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001420#endif
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001421 return(NULL);
1422 }
1423
1424 /*
1425 * Allocate a new node
1426 */
1427 if (ns == NULL)
1428 cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
1429 else
1430 cur = xmlNewDocRawNode(parent->doc, ns, name, content);
1431 if (cur == NULL) return(NULL);
1432
1433 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00001434 * add the new element at the end of the children list.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001435 */
1436 cur->type = XML_ELEMENT_NODE;
1437 cur->parent = parent;
1438 cur->doc = parent->doc;
Daniel Veillardcf461992000-03-14 18:30:20 +00001439 if (parent->children == NULL) {
1440 parent->children = cur;
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001441 parent->last = cur;
1442 } else {
1443 prev = parent->last;
1444 prev->next = cur;
1445 cur->prev = prev;
1446 parent->last = cur;
1447 }
1448
1449 return(cur);
1450}
1451
1452/**
Daniel Veillardcf461992000-03-14 18:30:20 +00001453 * xmlNewCharRef:
1454 * @doc: the document
1455 * @name: the char ref string, starting with # or "&# ... ;"
1456 *
1457 * Creation of a new character reference node.
1458 * Returns a pointer to the new node object.
1459 */
1460xmlNodePtr
1461xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
1462 xmlNodePtr cur;
1463
1464 /*
1465 * Allocate a new node and fill the fields.
1466 */
1467 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1468 if (cur == NULL) {
1469 fprintf(stderr, "xmlNewText : malloc failed\n");
1470 return(NULL);
1471 }
1472 memset(cur, 0, sizeof(xmlNode));
1473 cur->type = XML_ENTITY_REF_NODE;
1474
1475 cur->doc = doc;
1476 if (name[0] == '&') {
1477 int len;
1478 name++;
1479 len = xmlStrlen(name);
1480 if (name[len - 1] == ';')
1481 cur->name = xmlStrndup(name, len - 1);
1482 else
1483 cur->name = xmlStrndup(name, len);
1484 } else
1485 cur->name = xmlStrdup(name);
1486 return(cur);
1487}
1488
1489/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001490 * xmlNewReference:
1491 * @doc: the document
1492 * @name: the reference name, or the reference string with & and ;
1493 *
1494 * Creation of a new reference node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001495 * Returns a pointer to the new node object.
Daniel Veillardccb09631998-10-27 06:21:04 +00001496 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001497xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001498xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
Daniel Veillardccb09631998-10-27 06:21:04 +00001499 xmlNodePtr cur;
1500 xmlEntityPtr ent;
1501
1502 /*
1503 * Allocate a new node and fill the fields.
1504 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001505 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001506 if (cur == NULL) {
1507 fprintf(stderr, "xmlNewText : malloc failed\n");
1508 return(NULL);
1509 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001510 memset(cur, 0, sizeof(xmlNode));
Daniel Veillardccb09631998-10-27 06:21:04 +00001511 cur->type = XML_ENTITY_REF_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001512
Daniel Veillard10c6a8f1998-10-28 01:00:12 +00001513 cur->doc = doc;
Daniel Veillardccb09631998-10-27 06:21:04 +00001514 if (name[0] == '&') {
1515 int len;
1516 name++;
1517 len = xmlStrlen(name);
1518 if (name[len - 1] == ';')
1519 cur->name = xmlStrndup(name, len - 1);
1520 else
1521 cur->name = xmlStrndup(name, len);
1522 } else
1523 cur->name = xmlStrdup(name);
Daniel Veillardccb09631998-10-27 06:21:04 +00001524
1525 ent = xmlGetDocEntity(doc, cur->name);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001526 if (ent != NULL) {
1527#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00001528 cur->content = ent->content;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001529#else
1530 /*
1531 * CJN 11.18.99 this might be a problem, since the xmlBuffer gets
1532 * a copy of this pointer. Let's hope we don't manipulate it
1533 * later
1534 */
1535 cur->content = xmlBufferCreateSize(0);
1536 xmlBufferSetAllocationScheme(cur->content,
1537 xmlGetBufferAllocationScheme());
1538 if (ent->content != NULL)
1539 xmlBufferAdd(cur->content, ent->content, -1);
1540#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001541 cur->children = (xmlNodePtr) ent;
1542 }
Daniel Veillardccb09631998-10-27 06:21:04 +00001543 return(cur);
1544}
1545
1546/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001547 * xmlNewDocText:
1548 * @doc: the document
1549 * @content: the text content
1550 *
1551 * Creation of a new text node within a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001552 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001553 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001554xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001555xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001556 xmlNodePtr cur;
1557
1558 cur = xmlNewText(content);
1559 if (cur != NULL) cur->doc = doc;
1560 return(cur);
1561}
1562
Daniel Veillard97b58771998-10-20 06:14:16 +00001563/**
Daniel Veillardccb09631998-10-27 06:21:04 +00001564 * xmlNewTextLen:
Daniel Veillard97b58771998-10-20 06:14:16 +00001565 * @content: the text content
1566 * @len: the text len.
1567 *
1568 * Creation of a new text node with an extra parameter for the content's lenght
Daniel Veillard1e346af1999-02-22 10:33:01 +00001569 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001570 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001571xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001572xmlNewTextLen(const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001573 xmlNodePtr cur;
1574
1575 /*
1576 * Allocate a new node and fill the fields.
1577 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001578 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001579 if (cur == NULL) {
1580 fprintf(stderr, "xmlNewText : malloc failed\n");
1581 return(NULL);
1582 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001583 memset(cur, 0, sizeof(xmlNode));
1584 cur->type = XML_TEXT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001585
Daniel Veillard260a68f1998-08-13 03:39:55 +00001586 cur->name = xmlStrdup(xmlStringText);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001587 if (content != NULL) {
1588#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001589 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001590#else
1591 cur->content = xmlBufferCreateSize(len);
1592 xmlBufferSetAllocationScheme(cur->content,
1593 xmlGetBufferAllocationScheme());
1594 xmlBufferAdd(cur->content, content, len);
1595#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001596 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001597 return(cur);
1598}
1599
Daniel Veillard97b58771998-10-20 06:14:16 +00001600/**
1601 * xmlNewDocTextLen:
1602 * @doc: the document
1603 * @content: the text content
1604 * @len: the text len.
1605 *
1606 * Creation of a new text node with an extra content lenght parameter. The
1607 * text node pertain to a given document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001608 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001609 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001610xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001611xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001612 xmlNodePtr cur;
1613
1614 cur = xmlNewTextLen(content, len);
1615 if (cur != NULL) cur->doc = doc;
1616 return(cur);
1617}
1618
Daniel Veillard97b58771998-10-20 06:14:16 +00001619/**
1620 * xmlNewComment:
1621 * @content: the comment content
1622 *
1623 * Creation of a new node containing a comment.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001624 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001625 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001626xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001627xmlNewComment(const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001628 xmlNodePtr cur;
1629
1630 /*
1631 * Allocate a new node and fill the fields.
1632 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001633 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillard260a68f1998-08-13 03:39:55 +00001634 if (cur == NULL) {
1635 fprintf(stderr, "xmlNewComment : malloc failed\n");
1636 return(NULL);
1637 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001638 memset(cur, 0, sizeof(xmlNode));
1639 cur->type = XML_COMMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001640
Daniel Veillardcf461992000-03-14 18:30:20 +00001641 cur->name = xmlStrdup(xmlStringComment);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001642 if (content != NULL) {
1643#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00001644 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001645#else
1646 cur->content = xmlBufferCreateSize(0);
1647 xmlBufferSetAllocationScheme(cur->content,
1648 xmlGetBufferAllocationScheme());
1649 xmlBufferAdd(cur->content, content, -1);
1650#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001651 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00001652 return(cur);
1653}
1654
Daniel Veillard97b58771998-10-20 06:14:16 +00001655/**
Daniel Veillardb05deb71999-08-10 19:04:08 +00001656 * xmlNewCDataBlock:
1657 * @doc: the document
1658 * @content: the CData block content content
1659 * @len: the length of the block
1660 *
1661 * Creation of a new node containing a CData block.
1662 * Returns a pointer to the new node object.
1663 */
1664xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001665xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
Daniel Veillardb05deb71999-08-10 19:04:08 +00001666 xmlNodePtr cur;
1667
1668 /*
1669 * Allocate a new node and fill the fields.
1670 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00001671 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001672 if (cur == NULL) {
1673 fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1674 return(NULL);
1675 }
Daniel Veillardcf461992000-03-14 18:30:20 +00001676 memset(cur, 0, sizeof(xmlNode));
Daniel Veillardb05deb71999-08-10 19:04:08 +00001677 cur->type = XML_CDATA_SECTION_NODE;
Daniel Veillardcf461992000-03-14 18:30:20 +00001678
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001679 if (content != NULL) {
1680#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00001681 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00001682#else
1683 cur->content = xmlBufferCreateSize(len);
1684 xmlBufferSetAllocationScheme(cur->content,
1685 xmlGetBufferAllocationScheme());
1686 xmlBufferAdd(cur->content, content, len);
1687#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00001688 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00001689 return(cur);
1690}
1691
1692/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00001693 * xmlNewDocComment:
Daniel Veillard97b58771998-10-20 06:14:16 +00001694 * @doc: the document
1695 * @content: the comment content
1696 *
1697 * Creation of a new node containing a commentwithin a document.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001698 * Returns a pointer to the new node object.
Daniel Veillard97b58771998-10-20 06:14:16 +00001699 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001700xmlNodePtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00001701xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
Daniel Veillard0bef1311998-10-14 02:36:47 +00001702 xmlNodePtr cur;
1703
1704 cur = xmlNewComment(content);
1705 if (cur != NULL) cur->doc = doc;
1706 return(cur);
1707}
1708
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001709
Daniel Veillard97b58771998-10-20 06:14:16 +00001710/**
1711 * xmlNewChild:
1712 * @parent: the parent node
1713 * @ns: a namespace if any
1714 * @name: the name of the child
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001715 * @content: the XML content of the child if any.
Daniel Veillard97b58771998-10-20 06:14:16 +00001716 *
Daniel Veillardcf461992000-03-14 18:30:20 +00001717 * Creation of a new child element, added at the end of @parent children list.
Daniel Veillardccb09631998-10-27 06:21:04 +00001718 * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1719 * a child list containing the TEXTs and ENTITY_REFs node will be created.
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001720 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1721 * references, but XML special chars need to be escaped first by using
1722 * xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
1723 * support is not needed.
1724 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00001725 * Returns a pointer to the new node object.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001726 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001727xmlNodePtr
1728xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
Daniel Veillard11a48ec1999-11-23 10:40:46 +00001729 const xmlChar *name, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001730 xmlNodePtr cur, prev;
1731
1732 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001733#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001734 fprintf(stderr, "xmlNewChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001735#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001736 return(NULL);
1737 }
1738
1739 if (name == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001740#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00001741 fprintf(stderr, "xmlNewChild : name == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001742#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001743 return(NULL);
1744 }
1745
1746 /*
1747 * Allocate a new node
1748 */
1749 if (ns == NULL)
Daniel Veillardccb09631998-10-27 06:21:04 +00001750 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001751 else
Daniel Veillardccb09631998-10-27 06:21:04 +00001752 cur = xmlNewDocNode(parent->doc, ns, name, content);
Daniel Veillard260a68f1998-08-13 03:39:55 +00001753 if (cur == NULL) return(NULL);
1754
1755 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00001756 * add the new element at the end of the children list.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001757 */
Daniel Veillardccb09631998-10-27 06:21:04 +00001758 cur->type = XML_ELEMENT_NODE;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001759 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001760 cur->doc = parent->doc;
Daniel Veillardcf461992000-03-14 18:30:20 +00001761 if (parent->children == NULL) {
1762 parent->children = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001763 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001764 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001765 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001766 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00001767 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00001768 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00001769 }
1770
1771 return(cur);
1772}
1773
Daniel Veillard97b58771998-10-20 06:14:16 +00001774/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001775 * xmlAddNextSibling:
1776 * @cur: the child node
1777 * @elem: the new node
1778 *
1779 * Add a new element @elem as the next siblings of @cur
1780 * If the new element was already inserted in a document it is
1781 * first unlinked from its existing context.
1782 *
1783 * Returns the new element or NULL in case of error.
1784 */
1785xmlNodePtr
1786xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
1787 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001788#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001789 fprintf(stderr, "xmlAddNextSibling : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001790#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001791 return(NULL);
1792 }
1793 if (elem == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001794#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001795 fprintf(stderr, "xmlAddNextSibling : elem == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001796#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001797 return(NULL);
1798 }
1799
1800 xmlUnlinkNode(elem);
1801 elem->doc = cur->doc;
1802 elem->parent = cur->parent;
Daniel Veillard5d211f42000-04-07 17:00:24 +00001803 elem->prev = cur;
1804 elem->next = cur->next;
1805 cur->next = elem;
1806 if (elem->next != NULL)
1807 elem->next->prev = elem;
1808 if ((elem->parent != NULL) && (elem->parent->last == cur))
1809 elem->parent->last = elem;
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001810 return(elem);
1811}
1812
1813/**
1814 * xmlAddPrevSibling:
1815 * @cur: the child node
1816 * @elem: the new node
1817 *
1818 * Add a new element @elem as the previous siblings of @cur
1819 * If the new element was already inserted in a document it is
1820 * first unlinked from its existing context.
1821 *
1822 * Returns the new element or NULL in case of error.
1823 */
1824xmlNodePtr
1825xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
1826 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001827#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001828 fprintf(stderr, "xmlAddPrevSibling : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001829#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001830 return(NULL);
1831 }
1832 if (elem == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001833#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001834 fprintf(stderr, "xmlAddPrevSibling : elem == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001835#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001836 return(NULL);
1837 }
1838
1839 xmlUnlinkNode(elem);
1840 elem->doc = cur->doc;
1841 elem->parent = cur->parent;
Daniel Veillard5d211f42000-04-07 17:00:24 +00001842 elem->next = cur;
1843 elem->prev = cur->prev;
1844 cur->prev = elem;
1845 if (elem->prev != NULL)
1846 elem->prev->next = elem;
1847 if ((elem->parent != NULL) && (elem->parent->children == cur))
1848 elem->parent->children = elem;
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001849 return(elem);
1850}
1851
1852/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00001853 * xmlAddSibling:
1854 * @cur: the child node
1855 * @elem: the new node
1856 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001857 * Add a new element @elem to the list of siblings of @cur
1858 * If the new element was already inserted in a document it is
1859 * first unlinked from its existing context.
1860 *
1861 * Returns the new element or NULL in case of error.
Daniel Veillardb96e6431999-08-29 21:02:19 +00001862 */
1863xmlNodePtr
1864xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1865 xmlNodePtr parent;
1866
1867 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001868#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001869 fprintf(stderr, "xmlAddSibling : cur == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001870#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001871 return(NULL);
1872 }
1873
1874 if (elem == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001875#ifdef DEBUG_TREE
Daniel Veillardb96e6431999-08-29 21:02:19 +00001876 fprintf(stderr, "xmlAddSibling : elem == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001877#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00001878 return(NULL);
1879 }
1880
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001881 /*
1882 * Constant time is we can rely on the ->parent->last to find
1883 * the last sibling.
1884 */
1885 if ((cur->parent != NULL) &&
Daniel Veillardcf461992000-03-14 18:30:20 +00001886 (cur->parent->children != NULL) &&
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001887 (cur->parent->last != NULL) &&
1888 (cur->parent->last->next == NULL)) {
1889 cur = cur->parent->last;
1890 } else {
1891 while (cur->next != NULL) cur = cur->next;
Daniel Veillardb96e6431999-08-29 21:02:19 +00001892 }
1893
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00001894 xmlUnlinkNode(elem);
Daniel Veillardb96e6431999-08-29 21:02:19 +00001895 if (elem->doc == NULL)
1896 elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1897
1898 parent = cur->parent;
1899 elem->prev = cur;
1900 elem->next = NULL;
1901 elem->parent = parent;
1902 cur->next = elem;
1903 if (parent != NULL)
1904 parent->last = elem;
1905
1906 return(elem);
1907}
1908
1909/**
Daniel Veillard87b95392000-08-12 21:12:04 +00001910 * xmlAddChildList:
1911 * @parent: the parent node
1912 * @cur: the first node in the list
1913 *
1914 * Add a list of node at the end of the child list of the parent
1915 *
1916 * Returns the last child or NULL in case of error.
1917 */
1918xmlNodePtr
1919xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
1920 xmlNodePtr prev;
1921
1922 if (parent == NULL) {
1923#ifdef DEBUG_TREE
1924 fprintf(stderr, "xmlAddChild : parent == NULL\n");
1925#endif
1926 return(NULL);
1927 }
1928
1929 if (cur == NULL) {
1930#ifdef DEBUG_TREE
1931 fprintf(stderr, "xmlAddChild : child == NULL\n");
1932#endif
1933 return(NULL);
1934 }
1935
1936 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1937 (cur->doc != parent->doc)) {
1938#ifdef DEBUG_TREE
1939 fprintf(stderr, "Elements moved to a different document\n");
1940#endif
1941 }
1942
1943 /*
1944 * add the first element at the end of the children list.
1945 */
1946 if (parent->children == NULL) {
1947 parent->children = cur;
1948 } else {
1949 prev = parent->last;
1950 prev->next = cur;
1951 cur->prev = prev;
1952 }
1953 while (cur->next != NULL) {
1954 cur->parent = parent;
1955 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
1956 cur = cur->next;
1957 }
1958 cur->parent = parent;
1959 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
1960 parent->last = cur;
1961
1962 return(cur);
1963}
1964
1965/**
Daniel Veillard97b58771998-10-20 06:14:16 +00001966 * xmlAddChild:
1967 * @parent: the parent node
1968 * @cur: the child node
1969 *
1970 * Add a new child element, to @parent, at the end of the child list.
Daniel Veillard1e346af1999-02-22 10:33:01 +00001971 * Returns the child or NULL in case of error.
Daniel Veillard260a68f1998-08-13 03:39:55 +00001972 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00001973xmlNodePtr
1974xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00001975 xmlNodePtr prev;
1976
1977 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001978#ifdef DEBUG_TREE
Daniel Veillard10a2c651999-12-12 13:03:50 +00001979 fprintf(stderr, "xmlAddChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001980#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001981 return(NULL);
1982 }
1983
1984 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001985#ifdef DEBUG_TREE
Daniel Veillard10a2c651999-12-12 13:03:50 +00001986 fprintf(stderr, "xmlAddChild : child == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001987#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00001988 return(NULL);
1989 }
1990
Daniel Veillard0bef1311998-10-14 02:36:47 +00001991 if ((cur->doc != NULL) && (parent->doc != NULL) &&
1992 (cur->doc != parent->doc)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001993#ifdef DEBUG_TREE
Daniel Veillard0bef1311998-10-14 02:36:47 +00001994 fprintf(stderr, "Elements moved to a different document\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00001995#endif
Daniel Veillard0bef1311998-10-14 02:36:47 +00001996 }
1997
Daniel Veillard260a68f1998-08-13 03:39:55 +00001998 /*
Daniel Veillardcf461992000-03-14 18:30:20 +00001999 * add the new element at the end of the children list.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002000 */
2001 cur->parent = parent;
Daniel Veillard0bef1311998-10-14 02:36:47 +00002002 cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002003
Daniel Veillardccb09631998-10-27 06:21:04 +00002004 /*
2005 * Handle the case where parent->content != NULL, in that case it will
2006 * create a intermediate TEXT node.
2007 */
Daniel Veillardcf461992000-03-14 18:30:20 +00002008 if (((parent->type == XML_ELEMENT_NODE) || (parent->type == XML_TEXT_NODE)) &&
2009 (parent->content != NULL)) {
Daniel Veillardccb09631998-10-27 06:21:04 +00002010 xmlNodePtr text;
2011
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002012#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardccb09631998-10-27 06:21:04 +00002013 text = xmlNewDocText(parent->doc, parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002014#else
2015 text = xmlNewDocText(parent->doc, xmlBufferContent(parent->content));
2016#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00002017 if (text != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002018 text->next = parent->children;
Daniel Veillardccb09631998-10-27 06:21:04 +00002019 if (text->next != NULL)
2020 text->next->prev = text;
Daniel Veillardcf461992000-03-14 18:30:20 +00002021 parent->children = text;
Daniel Veillard1e346af1999-02-22 10:33:01 +00002022 UPDATE_LAST_CHILD(parent)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002023#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002024 xmlFree(parent->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002025#else
2026 xmlBufferFree(parent->content);
2027#endif
Daniel Veillardccb09631998-10-27 06:21:04 +00002028 parent->content = NULL;
2029 }
2030 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002031 if (parent->children == NULL) {
2032 parent->children = cur;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002033 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002034 } else {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002035 prev = parent->last;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002036 prev->next = cur;
Daniel Veillard0bef1311998-10-14 02:36:47 +00002037 cur->prev = prev;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002038 parent->last = cur;
Daniel Veillard260a68f1998-08-13 03:39:55 +00002039 }
2040
2041 return(cur);
2042}
2043
Daniel Veillard97b58771998-10-20 06:14:16 +00002044/**
2045 * xmlGetLastChild:
2046 * @parent: the parent node
2047 *
2048 * Search the last child of a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00002049 * Returns the last child or NULL if none.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002050 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002051xmlNodePtr
2052xmlGetLastChild(xmlNodePtr parent) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002053 if (parent == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002054#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002055 fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002056#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002057 return(NULL);
2058 }
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002059 return(parent->last);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002060}
2061
Daniel Veillard97b58771998-10-20 06:14:16 +00002062/**
2063 * xmlFreeNodeList:
2064 * @cur: the first node in the list
2065 *
2066 * Free a node and all its siblings, this is a recursive behaviour, all
Daniel Veillardcf461992000-03-14 18:30:20 +00002067 * the children are freed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002068 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002069void
2070xmlFreeNodeList(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002071 xmlNodePtr next;
2072 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002073#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002074 fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002075#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002076 return;
2077 }
2078 while (cur != NULL) {
2079 next = cur->next;
2080 xmlFreeNode(cur);
2081 cur = next;
2082 }
2083}
2084
Daniel Veillard97b58771998-10-20 06:14:16 +00002085/**
2086 * xmlFreeNode:
2087 * @cur: the node
2088 *
Daniel Veillardcf461992000-03-14 18:30:20 +00002089 * Free a node, this is a recursive behaviour, all the children are freed too.
2090 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002091 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002092void
2093xmlFreeNode(xmlNodePtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002094 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002095#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002096 fprintf(stderr, "xmlFreeNode : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002097#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002098 return;
2099 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002100 if (cur->type == XML_DTD_NODE)
2101 return;
Daniel Veillardccb09631998-10-27 06:21:04 +00002102 cur->doc = NULL;
2103 cur->parent = NULL;
2104 cur->next = NULL;
2105 cur->prev = NULL;
Daniel Veillardcf461992000-03-14 18:30:20 +00002106 if ((cur->children != NULL) &&
2107 (cur->type != XML_ENTITY_REF_NODE))
2108 xmlFreeNodeList(cur->children);
Daniel Veillardccb09631998-10-27 06:21:04 +00002109 if (cur->properties != NULL) xmlFreePropList(cur->properties);
2110 if (cur->type != XML_ENTITY_REF_NODE)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002111#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002112 if (cur->content != NULL) xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002113#else
2114 if (cur->content != NULL) xmlBufferFree(cur->content);
2115#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00002116 if (cur->name != NULL) xmlFree((char *) cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002117 if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
2118 memset(cur, -1, sizeof(xmlNode));
Daniel Veillard6454aec1999-09-02 22:04:43 +00002119 xmlFree(cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00002120}
2121
Daniel Veillard16253641998-10-28 22:58:05 +00002122/**
2123 * xmlUnlinkNode:
2124 * @cur: the node
2125 *
2126 * Unlink a node from it's current context, the node is not freed
2127 */
2128void
2129xmlUnlinkNode(xmlNodePtr cur) {
2130 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002131#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +00002132 fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002133#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002134 return;
2135 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002136 if ((cur->parent != NULL) && (cur->parent->children == cur))
2137 cur->parent->children = cur->next;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002138 if ((cur->parent != NULL) && (cur->parent->last == cur))
2139 cur->parent->last = cur->prev;
Daniel Veillard16253641998-10-28 22:58:05 +00002140 if (cur->next != NULL)
2141 cur->next->prev = cur->prev;
2142 if (cur->prev != NULL)
2143 cur->prev->next = cur->next;
2144 cur->next = cur->prev = NULL;
2145 cur->parent = NULL;
2146}
2147
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002148/**
2149 * xmlReplaceNode:
2150 * @old: the old node
2151 * @cur: the node
2152 *
2153 * Unlink the old node from it's current context, prune the new one
2154 * at the same place. If cur was already inserted in a document it is
2155 * first unlinked from its existing context.
2156 *
2157 * Returns the old node
2158 */
2159xmlNodePtr
2160xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
2161 if (old == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002162#ifdef DEBUG_TREE
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002163 fprintf(stderr, "xmlReplaceNode : old == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002164#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002165 return(NULL);
2166 }
2167 if (cur == NULL) {
2168 xmlUnlinkNode(old);
2169 return(old);
2170 }
2171 xmlUnlinkNode(cur);
2172 cur->doc = old->doc;
2173 cur->parent = old->parent;
2174 cur->next = old->next;
2175 if (cur->next != NULL)
2176 cur->next->prev = cur;
2177 cur->prev = old->prev;
2178 if (cur->prev != NULL)
2179 cur->prev->next = cur;
2180 if (cur->parent != NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002181 if (cur->parent->children == old)
2182 cur->parent->children = cur;
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002183 if (cur->parent->last == old)
2184 cur->parent->last = cur;
2185 }
2186 old->next = old->prev = NULL;
2187 old->parent = NULL;
2188 return(old);
2189}
2190
Daniel Veillard260a68f1998-08-13 03:39:55 +00002191/************************************************************************
2192 * *
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002193 * Copy operations *
2194 * *
2195 ************************************************************************/
2196
2197/**
2198 * xmlCopyNamespace:
2199 * @cur: the namespace
2200 *
2201 * Do a copy of the namespace.
2202 *
2203 * Returns: a new xmlNsPtr, or NULL in case of error.
2204 */
2205xmlNsPtr
2206xmlCopyNamespace(xmlNsPtr cur) {
2207 xmlNsPtr ret;
2208
2209 if (cur == NULL) return(NULL);
2210 switch (cur->type) {
2211 case XML_GLOBAL_NAMESPACE:
2212 ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
2213 break;
2214 case XML_LOCAL_NAMESPACE:
2215 ret = xmlNewNs(NULL, cur->href, cur->prefix);
2216 break;
2217 default:
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002218#ifdef DEBUG_TREE
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002219 fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002220#endif
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002221 return(NULL);
2222 }
2223 return(ret);
2224}
2225
2226/**
2227 * xmlCopyNamespaceList:
2228 * @cur: the first namespace
2229 *
2230 * Do a copy of an namespace list.
2231 *
2232 * Returns: a new xmlNsPtr, or NULL in case of error.
2233 */
2234xmlNsPtr
2235xmlCopyNamespaceList(xmlNsPtr cur) {
2236 xmlNsPtr ret = NULL;
2237 xmlNsPtr p = NULL,q;
2238
2239 while (cur != NULL) {
2240 q = xmlCopyNamespace(cur);
2241 if (p == NULL) {
2242 ret = p = q;
2243 } else {
2244 p->next = q;
2245 p = q;
2246 }
2247 cur = cur->next;
2248 }
2249 return(ret);
2250}
2251
2252/**
2253 * xmlCopyProp:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002254 * @target: the element where the attribute will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002255 * @cur: the attribute
2256 *
2257 * Do a copy of the attribute.
2258 *
2259 * Returns: a new xmlAttrPtr, or NULL in case of error.
2260 */
2261xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00002262xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002263 xmlAttrPtr ret;
2264
2265 if (cur == NULL) return(NULL);
Daniel Veillardcf461992000-03-14 18:30:20 +00002266 if (cur->parent != NULL)
2267 ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL);
2268 else if (cur->children != NULL)
2269 ret = xmlNewDocProp(cur->children->doc, cur->name, NULL);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002270 else
2271 ret = xmlNewDocProp(NULL, cur->name, NULL);
2272 if (ret == NULL) return(NULL);
Daniel Veillardcf461992000-03-14 18:30:20 +00002273 ret->parent = target;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002274
2275 if ((cur->ns != NULL) && (target != NULL)) {
2276 xmlNsPtr ns;
2277
2278 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
2279 ret->ns = ns;
2280 } else
2281 ret->ns = NULL;
2282
Daniel Veillardcf461992000-03-14 18:30:20 +00002283 if (cur->children != NULL)
2284 ret->children = xmlCopyNodeList(cur->children);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002285 return(ret);
2286}
2287
2288/**
2289 * xmlCopyPropList:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002290 * @target: the element where the attributes will be grafted
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002291 * @cur: the first attribute
2292 *
2293 * Do a copy of an attribute list.
2294 *
2295 * Returns: a new xmlAttrPtr, or NULL in case of error.
2296 */
2297xmlAttrPtr
Daniel Veillardb96e6431999-08-29 21:02:19 +00002298xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002299 xmlAttrPtr ret = NULL;
2300 xmlAttrPtr p = NULL,q;
2301
2302 while (cur != NULL) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00002303 q = xmlCopyProp(target, cur);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002304 if (p == NULL) {
2305 ret = p = q;
2306 } else {
2307 p->next = q;
Daniel Veillardcf461992000-03-14 18:30:20 +00002308 q->prev = p;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002309 p = q;
2310 }
2311 cur = cur->next;
2312 }
2313 return(ret);
2314}
2315
2316/*
Daniel Veillard11a48ec1999-11-23 10:40:46 +00002317 * NOTE abeut the CopyNode operations !
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002318 *
2319 * They are splitted into external and internal parts for one
2320 * tricky reason: namespaces. Doing a direct copy of a node
2321 * say RPM:Copyright without changing the namespace pointer to
2322 * something else can produce stale links. One way to do it is
2323 * to keep a reference counter but this doesn't work as soon
2324 * as one move the element or the subtree out of the scope of
2325 * the existing namespace. The actual solution seems to add
2326 * a copy of the namespace at the top of the copied tree if
2327 * not available in the subtree.
2328 * Hence two functions, the public front-end call the inner ones
2329 */
2330
2331static xmlNodePtr
2332xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
2333
2334static xmlNodePtr
2335xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
2336 int recursive) {
2337 xmlNodePtr ret;
2338
2339 if (node == NULL) return(NULL);
2340 /*
2341 * Allocate a new node and fill the fields.
2342 */
Daniel Veillard6454aec1999-09-02 22:04:43 +00002343 ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002344 if (ret == NULL) {
2345 fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
2346 return(NULL);
2347 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002348 memset(ret, 0, sizeof(xmlNode));
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002349 ret->type = node->type;
Daniel Veillardcf461992000-03-14 18:30:20 +00002350
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002351 ret->doc = doc;
2352 ret->parent = parent;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002353 if (node->name != NULL)
2354 ret->name = xmlStrdup(node->name);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002355 if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
2356#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002357 ret->content = xmlStrdup(node->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002358#else
2359 ret->content = xmlBufferCreateSize(xmlBufferLength(node->content));
2360 xmlBufferSetAllocationScheme(ret->content,
2361 xmlGetBufferAllocationScheme());
2362 xmlBufferAdd(ret->content,
2363 xmlBufferContent(node->content),
2364 xmlBufferLength(node->content));
2365#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00002366 }
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002367 if (parent != NULL)
2368 xmlAddChild(parent, ret);
2369
2370 if (!recursive) return(ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002371 if (node->nsDef != NULL)
2372 ret->nsDef = xmlCopyNamespaceList(node->nsDef);
2373
2374 if (node->ns != NULL) {
2375 xmlNsPtr ns;
2376
2377 ns = xmlSearchNs(doc, ret, node->ns->prefix);
2378 if (ns == NULL) {
2379 /*
2380 * Humm, we are copying an element whose namespace is defined
2381 * out of the new tree scope. Search it in the original tree
2382 * and add it at the top of the new tree
2383 */
2384 ns = xmlSearchNs(node->doc, node, node->ns->prefix);
2385 if (ns != NULL) {
2386 xmlNodePtr root = ret;
2387
2388 while (root->parent != NULL) root = root->parent;
2389 xmlNewNs(root, ns->href, ns->prefix);
2390 }
2391 } else {
2392 /*
2393 * reference the existing namespace definition in our own tree.
2394 */
2395 ret->ns = ns;
2396 }
2397 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002398 if (node->properties != NULL)
2399 ret->properties = xmlCopyPropList(ret, node->properties);
Daniel Veillardcf461992000-03-14 18:30:20 +00002400 if (node->children != NULL)
2401 ret->children = xmlStaticCopyNodeList(node->children, doc, ret);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002402 UPDATE_LAST_CHILD(ret)
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002403 return(ret);
2404}
2405
2406static xmlNodePtr
2407xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
2408 xmlNodePtr ret = NULL;
2409 xmlNodePtr p = NULL,q;
2410
2411 while (node != NULL) {
2412 q = xmlStaticCopyNode(node, doc, parent, 1);
Daniel Veillard06047432000-04-24 11:33:38 +00002413 if (ret == NULL) {
2414 q->prev = NULL;
2415 ret = p = q;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002416 } else {
Daniel Veillard06047432000-04-24 11:33:38 +00002417 p->next = q;
2418 q->prev = p;
2419 p = q;
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002420 }
2421 node = node->next;
2422 }
2423 return(ret);
2424}
2425
2426/**
2427 * xmlCopyNode:
2428 * @node: the node
2429 * @recursive: if 1 do a recursive copy.
2430 *
2431 * Do a copy of the node.
2432 *
2433 * Returns: a new xmlNodePtr, or NULL in case of error.
2434 */
2435xmlNodePtr
2436xmlCopyNode(xmlNodePtr node, int recursive) {
2437 xmlNodePtr ret;
2438
2439 ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
2440 return(ret);
2441}
2442
2443/**
2444 * xmlCopyNodeList:
2445 * @node: the first node in the list.
2446 *
2447 * Do a recursive copy of the node list.
2448 *
2449 * Returns: a new xmlNodePtr, or NULL in case of error.
2450 */
2451xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
2452 xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
2453 return(ret);
2454}
2455
2456/**
2457 * xmlCopyElement:
2458 * @elem: the element
2459 *
2460 * Do a copy of the element definition.
2461 *
2462 * Returns: a new xmlElementPtr, or NULL in case of error.
2463xmlElementPtr
2464xmlCopyElement(xmlElementPtr elem) {
2465 xmlElementPtr ret;
2466
2467 if (elem == NULL) return(NULL);
2468 ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
2469 if (ret == NULL) return(NULL);
2470 if (!recursive) return(ret);
2471 if (elem->properties != NULL)
2472 ret->properties = xmlCopyPropList(elem->properties);
2473
2474 if (elem->nsDef != NULL)
2475 ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
Daniel Veillardcf461992000-03-14 18:30:20 +00002476 if (elem->children != NULL)
2477 ret->children = xmlCopyElementList(elem->children);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002478 return(ret);
2479}
2480 */
2481
2482/**
2483 * xmlCopyDtd:
2484 * @dtd: the dtd
2485 *
2486 * Do a copy of the dtd.
2487 *
2488 * Returns: a new xmlDtdPtr, or NULL in case of error.
2489 */
2490xmlDtdPtr
2491xmlCopyDtd(xmlDtdPtr dtd) {
2492 xmlDtdPtr ret;
2493
2494 if (dtd == NULL) return(NULL);
2495 ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
2496 if (ret == NULL) return(NULL);
2497 if (dtd->entities != NULL)
2498 ret->entities = (void *) xmlCopyEntitiesTable(
2499 (xmlEntitiesTablePtr) dtd->entities);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002500 if (dtd->notations != NULL)
2501 ret->notations = (void *) xmlCopyNotationTable(
2502 (xmlNotationTablePtr) dtd->notations);
2503 if (dtd->elements != NULL)
2504 ret->elements = (void *) xmlCopyElementTable(
2505 (xmlElementTablePtr) dtd->elements);
2506 if (dtd->attributes != NULL)
2507 ret->attributes = (void *) xmlCopyAttributeTable(
2508 (xmlAttributeTablePtr) dtd->attributes);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002509 return(ret);
2510}
2511
2512/**
2513 * xmlCopyDoc:
2514 * @doc: the document
2515 * @recursive: if 1 do a recursive copy.
2516 *
2517 * Do a copy of the document info. If recursive, the content tree will
2518 * be copied too as well as Dtd, namespaces and entities.
2519 *
2520 * Returns: a new xmlDocPtr, or NULL in case of error.
2521 */
2522xmlDocPtr
2523xmlCopyDoc(xmlDocPtr doc, int recursive) {
2524 xmlDocPtr ret;
2525
2526 if (doc == NULL) return(NULL);
2527 ret = xmlNewDoc(doc->version);
2528 if (ret == NULL) return(NULL);
2529 if (doc->name != NULL)
Daniel Veillard6454aec1999-09-02 22:04:43 +00002530 ret->name = xmlMemStrdup(doc->name);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002531 if (doc->encoding != NULL)
2532 ret->encoding = xmlStrdup(doc->encoding);
2533 ret->compression = doc->compression;
2534 ret->standalone = doc->standalone;
2535 if (!recursive) return(ret);
2536
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00002537 if (doc->intSubset != NULL)
2538 ret->intSubset = xmlCopyDtd(doc->intSubset);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002539 if (doc->oldNs != NULL)
2540 ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
Daniel Veillardcf461992000-03-14 18:30:20 +00002541 if (doc->children != NULL)
Daniel Veillard06047432000-04-24 11:33:38 +00002542 ret->children = xmlStaticCopyNodeList(doc->children, ret,
2543 (xmlNodePtr)ret);
Daniel Veillardbe36afe1998-11-27 06:39:50 +00002544 return(ret);
2545}
2546
2547/************************************************************************
2548 * *
Daniel Veillard260a68f1998-08-13 03:39:55 +00002549 * Content access functions *
2550 * *
2551 ************************************************************************/
2552
Daniel Veillard97b58771998-10-20 06:14:16 +00002553/**
Daniel Veillard944b5ff1999-12-15 19:08:24 +00002554 * xmlDocGetRootElement:
2555 * @doc: the document
2556 *
Daniel Veillardcf461992000-03-14 18:30:20 +00002557 * Get the root element of the document (doc->children is a list
Daniel Veillard944b5ff1999-12-15 19:08:24 +00002558 * containing possibly comments, PIs, etc ...).
2559 *
2560 * Returns the xmlNodePtr for the root or NULL
2561 */
2562xmlNodePtr
2563xmlDocGetRootElement(xmlDocPtr doc) {
2564 xmlNodePtr ret;
2565
2566 if (doc == NULL) return(NULL);
Daniel Veillardcf461992000-03-14 18:30:20 +00002567 ret = doc->children;
Daniel Veillard944b5ff1999-12-15 19:08:24 +00002568 while (ret != NULL) {
2569 if (ret->type == XML_ELEMENT_NODE)
2570 return(ret);
2571 ret = ret->next;
2572 }
2573 return(ret);
2574}
2575
2576/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002577 * xmlDocSetRootElement:
2578 * @doc: the document
2579 * @root: the new document root element
2580 *
Daniel Veillardcf461992000-03-14 18:30:20 +00002581 * Set the root element of the document (doc->children is a list
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002582 * containing possibly comments, PIs, etc ...).
2583 *
2584 * Returns the old root element if any was found
2585 */
2586xmlNodePtr
2587xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
2588 xmlNodePtr old = NULL;
2589
2590 if (doc == NULL) return(NULL);
Daniel Veillardcf461992000-03-14 18:30:20 +00002591 old = doc->children;
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002592 while (old != NULL) {
2593 if (old->type == XML_ELEMENT_NODE)
2594 break;
2595 old = old->next;
2596 }
2597 if (old == NULL) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002598 if (doc->children == NULL) {
2599 doc->children = root;
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002600 } else {
Daniel Veillardcf461992000-03-14 18:30:20 +00002601 xmlAddSibling(doc->children, root);
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002602 }
2603 } else {
2604 xmlReplaceNode(old, root);
2605 }
2606 return(old);
2607}
2608
2609/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00002610 * xmlNodeSetLang:
2611 * @cur: the node being changed
2612 * @lang: the langage description
2613 *
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002614 * Set the language of a node, i.e. the values of the xml:lang
2615 * attribute.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002616 */
2617void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002618xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002619 if (cur == NULL) return;
2620 switch(cur->type) {
2621 case XML_TEXT_NODE:
2622 case XML_CDATA_SECTION_NODE:
2623 case XML_COMMENT_NODE:
2624 case XML_DOCUMENT_NODE:
2625 case XML_DOCUMENT_TYPE_NODE:
2626 case XML_DOCUMENT_FRAG_NODE:
2627 case XML_NOTATION_NODE:
2628 case XML_HTML_DOCUMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +00002629 case XML_DTD_NODE:
2630 case XML_ELEMENT_DECL:
2631 case XML_ATTRIBUTE_DECL:
2632 case XML_ENTITY_DECL:
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002633 case XML_PI_NODE:
2634 case XML_ENTITY_REF_NODE:
2635 case XML_ENTITY_NODE:
Daniel Veillard04698d92000-09-17 16:00:22 +00002636#ifdef LIBXML_SGML_ENABLED
2637 case XML_SGML_DOCUMENT_NODE:
2638#endif
Daniel Veillard39c7d712000-09-10 16:14:55 +00002639 return;
2640 case XML_ELEMENT_NODE:
2641 case XML_ATTRIBUTE_NODE:
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002642 break;
2643 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00002644 xmlSetProp(cur, BAD_CAST "xml:lang", lang);
2645}
2646
2647/**
2648 * xmlNodeGetLang:
2649 * @cur: the node being checked
2650 *
2651 * Searches the language of a node, i.e. the values of the xml:lang
2652 * attribute or the one carried by the nearest ancestor.
2653 *
2654 * Returns a pointer to the lang value, or NULL if not found
Daniel Veillarda819dac1999-11-24 18:04:22 +00002655 * It's up to the caller to free the memory.
Daniel Veillardb96e6431999-08-29 21:02:19 +00002656 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00002657xmlChar *
Daniel Veillardb96e6431999-08-29 21:02:19 +00002658xmlNodeGetLang(xmlNodePtr cur) {
Daniel Veillarda819dac1999-11-24 18:04:22 +00002659 xmlChar *lang;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002660
2661 while (cur != NULL) {
2662 lang = xmlGetProp(cur, BAD_CAST "xml:lang");
2663 if (lang != NULL)
2664 return(lang);
2665 cur = cur->parent;
2666 }
2667 return(NULL);
2668}
2669
2670/**
Daniel Veillardcf461992000-03-14 18:30:20 +00002671 * xmlNodeGetSpacePreserve:
2672 * @cur: the node being checked
2673 *
2674 * Searches the language of a node, i.e. the values of the xml:space
2675 * attribute or the one carried by the nearest ancestor.
2676 *
2677 * Returns -1 if xml:space is not inheried, 0 if "default", 1 if "preserve"
2678 */
2679int
2680xmlNodeGetSpacePreserve(xmlNodePtr cur) {
2681 xmlChar *space;
2682
2683 while (cur != NULL) {
2684 space = xmlGetProp(cur, BAD_CAST "xml:space");
2685 if (space != NULL) {
Daniel Veillard8b5dd832000-10-01 20:28:44 +00002686 if (xmlStrEqual(space, BAD_CAST "preserve")) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002687 xmlFree(space);
2688 return(1);
2689 }
Daniel Veillard8b5dd832000-10-01 20:28:44 +00002690 if (xmlStrEqual(space, BAD_CAST "default")) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002691 xmlFree(space);
2692 return(0);
2693 }
2694 xmlFree(space);
2695 }
2696 cur = cur->parent;
2697 }
2698 return(-1);
2699}
2700
2701/**
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002702 * xmlNodeSetName:
2703 * @cur: the node being changed
2704 * @name: the new tag name
2705 *
2706 * Searches the language of a node, i.e. the values of the xml:lang
2707 * attribute or the one carried by the nearest ancestor.
2708 */
2709void
2710xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
2711 if (cur == NULL) return;
2712 if (name == NULL) return;
2713 switch(cur->type) {
2714 case XML_TEXT_NODE:
2715 case XML_CDATA_SECTION_NODE:
2716 case XML_COMMENT_NODE:
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002717 case XML_DOCUMENT_TYPE_NODE:
2718 case XML_DOCUMENT_FRAG_NODE:
2719 case XML_NOTATION_NODE:
2720 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard04698d92000-09-17 16:00:22 +00002721#ifdef LIBXML_SGML_ENABLED
2722 case XML_SGML_DOCUMENT_NODE:
2723#endif
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002724 return;
2725 case XML_ELEMENT_NODE:
2726 case XML_ATTRIBUTE_NODE:
2727 case XML_PI_NODE:
2728 case XML_ENTITY_REF_NODE:
2729 case XML_ENTITY_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +00002730 case XML_DTD_NODE:
2731 case XML_DOCUMENT_NODE:
2732 case XML_ELEMENT_DECL:
2733 case XML_ATTRIBUTE_DECL:
2734 case XML_ENTITY_DECL:
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00002735 break;
2736 }
2737 if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
2738 cur->name = xmlStrdup(name);
2739}
2740
2741/**
Daniel Veillard10a2c651999-12-12 13:03:50 +00002742 * xmlNodeGetBase:
2743 * @doc: the document the node pertains to
2744 * @cur: the node being checked
2745 *
2746 * Searches for the BASE URL. The code should work on both XML
2747 * and HTML document even if base mechanisms are completely different.
2748 *
2749 * Returns a pointer to the base URL, or NULL if not found
2750 * It's up to the caller to free the memory.
2751 */
2752xmlChar *
2753xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
2754 xmlChar *base;
2755
2756 if ((cur == NULL) && (doc == NULL))
2757 return(NULL);
2758 if (doc == NULL) doc = cur->doc;
2759 if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002760 cur = doc->children;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002761 while ((cur != NULL) && (cur->name != NULL)) {
Daniel Veillard39c7d712000-09-10 16:14:55 +00002762 if (cur->type == XML_ENTITY_DECL) {
2763 /* TODO: we are crossing entity boundaries */
2764 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00002765 if (cur->type != XML_ELEMENT_NODE) {
2766 cur = cur->next;
2767 continue;
2768 }
Daniel Veillardb656ebe2000-09-22 13:51:48 +00002769 if (!xmlStrcasecmp(cur->name, BAD_CAST "html")) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002770 cur = cur->children;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002771 continue;
2772 }
Daniel Veillardb656ebe2000-09-22 13:51:48 +00002773 if (!xmlStrcasecmp(cur->name, BAD_CAST "head")) {
Daniel Veillardcf461992000-03-14 18:30:20 +00002774 cur = cur->children;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002775 continue;
2776 }
Daniel Veillardb656ebe2000-09-22 13:51:48 +00002777 if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) {
2778 return(xmlGetProp(cur, BAD_CAST "href"));
Daniel Veillard10a2c651999-12-12 13:03:50 +00002779 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002780 cur = cur->next;
Daniel Veillard10a2c651999-12-12 13:03:50 +00002781 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002782 if ((doc != NULL) && (doc->URL != NULL))
2783 return(xmlStrdup(doc->URL));
Daniel Veillard10a2c651999-12-12 13:03:50 +00002784 return(NULL);
2785 }
2786 while (cur != NULL) {
2787 base = xmlGetProp(cur, BAD_CAST "xml:base");
2788 if (base != NULL)
2789 return(base);
2790 cur = cur->parent;
2791 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002792 if ((doc != NULL) && (doc->URL != NULL))
2793 return(xmlStrdup(doc->URL));
Daniel Veillard10a2c651999-12-12 13:03:50 +00002794 return(NULL);
2795}
2796
2797/**
Daniel Veillard16253641998-10-28 22:58:05 +00002798 * xmlNodeGetContent:
2799 * @cur: the node being read
2800 *
2801 * Read the value of a node, this can be either the text carried
2802 * directly by this node if it's a TEXT node or the aggregate string
2803 * of the values carried by this node child's (TEXT and ENTITY_REF).
2804 * Entity references are substitued.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002805 * Returns a new xmlChar * or NULL if no content is available.
Daniel Veillard5099ae81999-04-21 20:12:07 +00002806 * It's up to the caller to free the memory.
Daniel Veillard16253641998-10-28 22:58:05 +00002807 */
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002808xmlChar *
Daniel Veillard16253641998-10-28 22:58:05 +00002809xmlNodeGetContent(xmlNodePtr cur) {
2810 if (cur == NULL) return(NULL);
2811 switch (cur->type) {
2812 case XML_DOCUMENT_FRAG_NODE:
2813 case XML_ELEMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +00002814 return(xmlNodeListGetString(cur->doc, cur->children, 1));
Daniel Veillard16253641998-10-28 22:58:05 +00002815 break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002816 case XML_ATTRIBUTE_NODE: {
2817 xmlAttrPtr attr = (xmlAttrPtr) cur;
Daniel Veillardcf461992000-03-14 18:30:20 +00002818 if (attr->parent != NULL)
2819 return(xmlNodeListGetString(attr->parent->doc, attr->children, 1));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002820 else
Daniel Veillardcf461992000-03-14 18:30:20 +00002821 return(xmlNodeListGetString(NULL, attr->children, 1));
Daniel Veillardb96e6431999-08-29 21:02:19 +00002822 break;
2823 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002824 case XML_COMMENT_NODE:
Daniel Veillardb96e6431999-08-29 21:02:19 +00002825 case XML_PI_NODE:
2826 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002827#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00002828 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002829#else
2830 return(xmlStrdup(xmlBufferContent(cur->content)));
2831#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00002832 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002833 case XML_ENTITY_REF_NODE:
Daniel Veillarddbfd6411999-12-28 16:35:14 +00002834 /*
2835 * Locate the entity, and get it's content
2836 * @@@
2837 */
2838 return(NULL);
Daniel Veillard16253641998-10-28 22:58:05 +00002839 case XML_ENTITY_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002840 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002841 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002842 case XML_DOCUMENT_TYPE_NODE:
2843 case XML_NOTATION_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +00002844 case XML_DTD_NODE:
Daniel Veillard04698d92000-09-17 16:00:22 +00002845#ifdef LIBXML_SGML_ENABLED
2846 case XML_SGML_DOCUMENT_NODE:
2847#endif
Daniel Veillardcf461992000-03-14 18:30:20 +00002848 return(NULL);
2849 case XML_ELEMENT_DECL:
2850 /* TODO !!! */
2851 return(NULL);
2852 case XML_ATTRIBUTE_DECL:
2853 /* TODO !!! */
2854 return(NULL);
2855 case XML_ENTITY_DECL:
2856 /* TODO !!! */
Daniel Veillard16253641998-10-28 22:58:05 +00002857 return(NULL);
Daniel Veillardb05deb71999-08-10 19:04:08 +00002858 case XML_CDATA_SECTION_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002859 case XML_TEXT_NODE:
2860 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002861#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002862 return(xmlStrdup(cur->content));
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002863#else
2864 return(xmlStrdup(xmlBufferContent(cur->content)));
2865#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002866 return(NULL);
2867 }
2868 return(NULL);
2869}
2870
2871/**
Daniel Veillard97b58771998-10-20 06:14:16 +00002872 * xmlNodeSetContent:
2873 * @cur: the node being modified
2874 * @content: the new value of the content
2875 *
2876 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002877 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002878void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002879xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002880 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002881#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00002882 fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002883#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002884 return;
2885 }
Daniel Veillard16253641998-10-28 22:58:05 +00002886 switch (cur->type) {
2887 case XML_DOCUMENT_FRAG_NODE:
2888 case XML_ELEMENT_NODE:
2889 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002890#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002891 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002892#else
2893 xmlBufferFree(cur->content);
2894#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002895 cur->content = NULL;
2896 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002897 if (cur->children != NULL) xmlFreeNodeList(cur->children);
2898 cur->children = xmlStringGetNodeList(cur->doc, content);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002899 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002900 break;
2901 case XML_ATTRIBUTE_NODE:
2902 break;
2903 case XML_TEXT_NODE:
2904 case XML_CDATA_SECTION_NODE:
2905 case XML_ENTITY_REF_NODE:
2906 case XML_ENTITY_NODE:
2907 case XML_PI_NODE:
2908 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002909 if (cur->content != NULL) {
2910#ifndef XML_USE_BUFFER_CONTENT
2911 xmlFree(cur->content);
2912#else
2913 xmlBufferFree(cur->content);
2914#endif
2915 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002916 if (cur->children != NULL) xmlFreeNodeList(cur->children);
2917 cur->last = cur->children = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002918 if (content != NULL) {
2919#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00002920 cur->content = xmlStrdup(content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002921#else
2922 cur->content = xmlBufferCreateSize(0);
2923 xmlBufferSetAllocationScheme(cur->content,
2924 xmlGetBufferAllocationScheme());
2925 xmlBufferAdd(cur->content, content, -1);
2926#endif
2927 } else
Daniel Veillard16253641998-10-28 22:58:05 +00002928 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00002929 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002930 case XML_DOCUMENT_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00002931 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00002932 case XML_DOCUMENT_TYPE_NODE:
Daniel Veillard04698d92000-09-17 16:00:22 +00002933#ifdef LIBXML_SGML_ENABLED
2934 case XML_SGML_DOCUMENT_NODE:
2935#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002936 break;
2937 case XML_NOTATION_NODE:
2938 break;
Daniel Veillardcf461992000-03-14 18:30:20 +00002939 case XML_DTD_NODE:
2940 break;
2941 case XML_ELEMENT_DECL:
2942 /* TODO !!! */
2943 break;
2944 case XML_ATTRIBUTE_DECL:
2945 /* TODO !!! */
2946 break;
2947 case XML_ENTITY_DECL:
2948 /* TODO !!! */
2949 break;
Daniel Veillard16253641998-10-28 22:58:05 +00002950 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00002951}
2952
Daniel Veillard97b58771998-10-20 06:14:16 +00002953/**
2954 * xmlNodeSetContentLen:
2955 * @cur: the node being modified
2956 * @content: the new value of the content
2957 * @len: the size of @content
2958 *
2959 * Replace the content of a node.
Daniel Veillard260a68f1998-08-13 03:39:55 +00002960 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00002961void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00002962xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00002963 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002964#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +00002965 fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00002966#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00002967 return;
2968 }
Daniel Veillard16253641998-10-28 22:58:05 +00002969 switch (cur->type) {
2970 case XML_DOCUMENT_FRAG_NODE:
2971 case XML_ELEMENT_NODE:
2972 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002973#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00002974 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002975#else
2976 xmlBufferFree(cur->content);
2977#endif
Daniel Veillard16253641998-10-28 22:58:05 +00002978 cur->content = NULL;
2979 }
Daniel Veillardcf461992000-03-14 18:30:20 +00002980 if (cur->children != NULL) xmlFreeNodeList(cur->children);
2981 cur->children = xmlStringLenGetNodeList(cur->doc, content, len);
Daniel Veillard1e346af1999-02-22 10:33:01 +00002982 UPDATE_LAST_CHILD(cur)
Daniel Veillard16253641998-10-28 22:58:05 +00002983 break;
2984 case XML_ATTRIBUTE_NODE:
2985 break;
2986 case XML_TEXT_NODE:
2987 case XML_CDATA_SECTION_NODE:
2988 case XML_ENTITY_REF_NODE:
2989 case XML_ENTITY_NODE:
2990 case XML_PI_NODE:
2991 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00002992 case XML_NOTATION_NODE:
2993 if (cur->content != NULL) {
2994#ifndef XML_USE_BUFFER_CONTENT
2995 xmlFree(cur->content);
2996#else
2997 xmlBufferFree(cur->content);
2998#endif
2999 }
Daniel Veillardcf461992000-03-14 18:30:20 +00003000 if (cur->children != NULL) xmlFreeNodeList(cur->children);
3001 cur->children = cur->last = NULL;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003002 if (content != NULL) {
3003#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00003004 cur->content = xmlStrndup(content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003005#else
3006 cur->content = xmlBufferCreateSize(len);
3007 xmlBufferSetAllocationScheme(cur->content,
3008 xmlGetBufferAllocationScheme());
3009 xmlBufferAdd(cur->content, content, len);
3010#endif
3011 } else
Daniel Veillard16253641998-10-28 22:58:05 +00003012 cur->content = NULL;
Daniel Veillardb96e6431999-08-29 21:02:19 +00003013 break;
Daniel Veillard16253641998-10-28 22:58:05 +00003014 case XML_DOCUMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +00003015 case XML_DTD_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00003016 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00003017 case XML_DOCUMENT_TYPE_NODE:
Daniel Veillard04698d92000-09-17 16:00:22 +00003018#ifdef LIBXML_SGML_ENABLED
3019 case XML_SGML_DOCUMENT_NODE:
3020#endif
Daniel Veillard16253641998-10-28 22:58:05 +00003021 break;
Daniel Veillardcf461992000-03-14 18:30:20 +00003022 case XML_ELEMENT_DECL:
3023 /* TODO !!! */
3024 break;
3025 case XML_ATTRIBUTE_DECL:
3026 /* TODO !!! */
3027 break;
3028 case XML_ENTITY_DECL:
3029 /* TODO !!! */
3030 break;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003031 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003032}
3033
Daniel Veillard97b58771998-10-20 06:14:16 +00003034/**
3035 * xmlNodeAddContentLen:
3036 * @cur: the node being modified
3037 * @content: extra content
3038 * @len: the size of @content
3039 *
3040 * Append the extra substring to the node content.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003041 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003042void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003043xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003044 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003045#ifdef DEBUG_TREE
Daniel Veillard16253641998-10-28 22:58:05 +00003046 fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003047#endif
Daniel Veillard16253641998-10-28 22:58:05 +00003048 return;
3049 }
3050 if (len <= 0) return;
3051 switch (cur->type) {
3052 case XML_DOCUMENT_FRAG_NODE:
3053 case XML_ELEMENT_NODE: {
Daniel Veillard32bc74e2000-07-14 14:49:25 +00003054 xmlNodePtr last = NULL, newNode;
Daniel Veillard16253641998-10-28 22:58:05 +00003055
Daniel Veillardcf461992000-03-14 18:30:20 +00003056 if (cur->children != NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003057 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00003058 } else {
3059 if (cur->content != NULL) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003060#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardcf461992000-03-14 18:30:20 +00003061 cur->children = xmlStringGetNodeList(cur->doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003062#else
Daniel Veillardcf461992000-03-14 18:30:20 +00003063 cur->children = xmlStringGetNodeList(cur->doc,
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003064 xmlBufferContent(cur->content));
3065#endif
Daniel Veillard1e346af1999-02-22 10:33:01 +00003066 UPDATE_LAST_CHILD(cur)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003067#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard6454aec1999-09-02 22:04:43 +00003068 xmlFree(cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003069#else
3070 xmlBufferFree(cur->content);
3071#endif
Daniel Veillard16253641998-10-28 22:58:05 +00003072 cur->content = NULL;
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003073 last = cur->last;
Daniel Veillard16253641998-10-28 22:58:05 +00003074 }
3075 }
Daniel Veillard32bc74e2000-07-14 14:49:25 +00003076 newNode = xmlNewTextLen(content, len);
3077 if (newNode != NULL) {
3078 xmlAddChild(cur, newNode);
3079 if ((last != NULL) && (last->next == newNode)) {
3080 xmlTextMerge(last, newNode);
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00003081 }
Daniel Veillard16253641998-10-28 22:58:05 +00003082 }
3083 break;
3084 }
3085 case XML_ATTRIBUTE_NODE:
3086 break;
3087 case XML_TEXT_NODE:
3088 case XML_CDATA_SECTION_NODE:
3089 case XML_ENTITY_REF_NODE:
3090 case XML_ENTITY_NODE:
3091 case XML_PI_NODE:
3092 case XML_COMMENT_NODE:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003093 case XML_NOTATION_NODE:
3094 if (content != NULL) {
3095#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00003096 cur->content = xmlStrncat(cur->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003097#else
3098 xmlBufferAdd(cur->content, content, len);
3099#endif
3100 }
Daniel Veillard16253641998-10-28 22:58:05 +00003101 case XML_DOCUMENT_NODE:
Daniel Veillardcf461992000-03-14 18:30:20 +00003102 case XML_DTD_NODE:
Daniel Veillard7c1206f1999-10-14 09:10:25 +00003103 case XML_HTML_DOCUMENT_NODE:
Daniel Veillard16253641998-10-28 22:58:05 +00003104 case XML_DOCUMENT_TYPE_NODE:
Daniel Veillard04698d92000-09-17 16:00:22 +00003105#ifdef LIBXML_SGML_ENABLED
3106 case XML_SGML_DOCUMENT_NODE:
3107#endif
Daniel Veillard16253641998-10-28 22:58:05 +00003108 break;
Daniel Veillardcf461992000-03-14 18:30:20 +00003109 case XML_ELEMENT_DECL:
3110 case XML_ATTRIBUTE_DECL:
3111 case XML_ENTITY_DECL:
3112 break;
Daniel Veillard16253641998-10-28 22:58:05 +00003113 }
3114}
3115
3116/**
3117 * xmlNodeAddContent:
3118 * @cur: the node being modified
3119 * @content: extra content
3120 *
3121 * Append the extra substring to the node content.
3122 */
3123void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003124xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
Daniel Veillard16253641998-10-28 22:58:05 +00003125 int len;
3126
3127 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003128#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00003129 fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003130#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003131 return;
3132 }
Daniel Veillard16253641998-10-28 22:58:05 +00003133 if (content == NULL) return;
3134 len = xmlStrlen(content);
3135 xmlNodeAddContentLen(cur, content, len);
3136}
3137
3138/**
3139 * xmlTextMerge:
3140 * @first: the first text node
3141 * @second: the second text node being merged
3142 *
3143 * Merge two text nodes into one
Daniel Veillard1e346af1999-02-22 10:33:01 +00003144 * Returns the first text node augmented
Daniel Veillard16253641998-10-28 22:58:05 +00003145 */
3146xmlNodePtr
3147xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
3148 if (first == NULL) return(second);
3149 if (second == NULL) return(first);
3150 if (first->type != XML_TEXT_NODE) return(first);
3151 if (second->type != XML_TEXT_NODE) return(first);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003152#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard16253641998-10-28 22:58:05 +00003153 xmlNodeAddContent(first, second->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003154#else
3155 xmlNodeAddContent(first, xmlBufferContent(second->content));
3156#endif
Daniel Veillard16253641998-10-28 22:58:05 +00003157 xmlUnlinkNode(second);
3158 xmlFreeNode(second);
3159 return(first);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003160}
3161
Daniel Veillard97b58771998-10-20 06:14:16 +00003162/**
Daniel Veillardb96e6431999-08-29 21:02:19 +00003163 * xmlGetNsList:
3164 * @doc: the document
3165 * @node: the current node
3166 *
3167 * Search all the namespace applying to a given element.
3168 * Returns an NULL terminated array of all the xmlNsPtr found
3169 * that need to be freed by the caller or NULL if no
3170 * namespace if defined
3171 */
3172xmlNsPtr *
3173xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
3174 xmlNsPtr cur;
3175 xmlNsPtr *ret = NULL;
3176 int nbns = 0;
3177 int maxns = 10;
3178 int i;
3179
3180 while (node != NULL) {
3181 cur = node->nsDef;
3182 while (cur != NULL) {
3183 if (ret == NULL) {
Daniel Veillard6454aec1999-09-02 22:04:43 +00003184 ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
Daniel Veillardb96e6431999-08-29 21:02:19 +00003185 if (ret == NULL) {
3186 fprintf(stderr, "xmlGetNsList : out of memory!\n");
3187 return(NULL);
3188 }
3189 ret[nbns] = NULL;
3190 }
3191 for (i = 0;i < nbns;i++) {
3192 if ((cur->prefix == ret[i]->prefix) ||
Daniel Veillard8b5dd832000-10-01 20:28:44 +00003193 (xmlStrEqual(cur->prefix, ret[i]->prefix))) break;
Daniel Veillardb96e6431999-08-29 21:02:19 +00003194 }
3195 if (i >= nbns) {
3196 if (nbns >= maxns) {
3197 maxns *= 2;
Daniel Veillard6454aec1999-09-02 22:04:43 +00003198 ret = (xmlNsPtr *) xmlRealloc(ret,
Daniel Veillardb96e6431999-08-29 21:02:19 +00003199 (maxns + 1) * sizeof(xmlNsPtr));
3200 if (ret == NULL) {
3201 fprintf(stderr, "xmlGetNsList : realloc failed!\n");
3202 return(NULL);
3203 }
3204 }
3205 ret[nbns++] = cur;
3206 ret[nbns] = NULL;
3207 }
3208
3209 cur = cur->next;
3210 }
3211 node = node->parent;
3212 }
3213 return(ret);
3214}
3215
3216/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003217 * xmlSearchNs:
3218 * @doc: the document
3219 * @node: the current node
3220 * @nameSpace: the namespace string
Daniel Veillard260a68f1998-08-13 03:39:55 +00003221 *
Daniel Veillard97b58771998-10-20 06:14:16 +00003222 * Search a Ns registered under a given name space for a document.
3223 * recurse on the parents until it finds the defined namespace
3224 * or return NULL otherwise.
3225 * @nameSpace can be NULL, this is a search for the default namespace.
Daniel Veillarde0854c32000-08-27 21:12:29 +00003226 * We don't allow to cross entities boundaries. If you don't declare
3227 * the namespace within those you will be in troubles !!! A warning
3228 * is generated to cover this case.
3229 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003230 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003231 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003232xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003233xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003234 xmlNsPtr cur;
3235
Daniel Veillard62ba71e1999-12-16 17:52:19 +00003236 if (node == NULL) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003237 while (node != NULL) {
Daniel Veillarde0854c32000-08-27 21:12:29 +00003238 if ((node->type == XML_ENTITY_REF_NODE) ||
3239 (node->type == XML_ENTITY_NODE) ||
3240 (node->type == XML_ENTITY_DECL))
3241 return(NULL);
Daniel Veillardcf461992000-03-14 18:30:20 +00003242 if (node->type == XML_ELEMENT_NODE) {
3243 cur = node->nsDef;
3244 while (cur != NULL) {
Daniel Veillarde0854c32000-08-27 21:12:29 +00003245 if ((cur->prefix == NULL) && (nameSpace == NULL) &&
3246 (cur->href != NULL))
Daniel Veillardcf461992000-03-14 18:30:20 +00003247 return(cur);
3248 if ((cur->prefix != NULL) && (nameSpace != NULL) &&
Daniel Veillarde0854c32000-08-27 21:12:29 +00003249 (cur->href != NULL) &&
Daniel Veillard8b5dd832000-10-01 20:28:44 +00003250 (xmlStrEqual(cur->prefix, nameSpace)))
Daniel Veillardcf461992000-03-14 18:30:20 +00003251 return(cur);
3252 cur = cur->next;
3253 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003254 }
3255 node = node->parent;
3256 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003257 return(NULL);
3258}
3259
Daniel Veillard97b58771998-10-20 06:14:16 +00003260/**
3261 * xmlSearchNsByHref:
3262 * @doc: the document
3263 * @node: the current node
3264 * @href: the namespace value
3265 *
3266 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
3267 * the defined namespace or return NULL otherwise.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003268 * Returns the namespace pointer or NULL.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003269 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003270xmlNsPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003271xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003272 xmlNsPtr cur;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003273 xmlNodePtr orig = node;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003274
Daniel Veillard10a2c651999-12-12 13:03:50 +00003275 if ((node == NULL) || (href == NULL)) return(NULL);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003276 while (node != NULL) {
3277 cur = node->nsDef;
3278 while (cur != NULL) {
3279 if ((cur->href != NULL) && (href != NULL) &&
Daniel Veillard8b5dd832000-10-01 20:28:44 +00003280 (xmlStrEqual(cur->href, href))) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003281 /*
3282 * Check that the prefix is not shadowed between orig and node
3283 */
3284 xmlNodePtr check = orig;
3285 xmlNsPtr tst;
3286
3287 while (check != node) {
3288 tst = check->nsDef;
3289 while (tst != NULL) {
3290 if ((tst->prefix == NULL) && (cur->prefix == NULL))
3291 goto shadowed;
3292 if ((tst->prefix != NULL) && (cur->prefix != NULL) &&
Daniel Veillard8b5dd832000-10-01 20:28:44 +00003293 (xmlStrEqual(tst->prefix, cur->prefix)))
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003294 goto shadowed;
3295 tst = tst->next;
3296 }
3297 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003298 return(cur);
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003299 }
3300shadowed:
Daniel Veillard260a68f1998-08-13 03:39:55 +00003301 cur = cur->next;
3302 }
3303 node = node->parent;
3304 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003305 return(NULL);
3306}
3307
3308/**
3309 * xmlNewReconciliedNs
3310 * @doc: the document
3311 * @tree: a node expected to hold the new namespace
3312 * @ns: the original namespace
3313 *
3314 * This function tries to locate a namespace definition in a tree
3315 * ancestors, or create a new namespace definition node similar to
3316 * @ns trying to reuse the same prefix. However if the given prefix is
3317 * null (default namespace) or reused within the subtree defined by
3318 * @tree or on one of its ancestors then a new prefix is generated.
3319 * Returns the (new) namespace definition or NULL in case of error
3320 */
3321xmlNsPtr
3322xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
3323 xmlNsPtr def;
3324 xmlChar prefix[50];
3325 int counter = 1;
3326
3327 if (tree == NULL) {
3328#ifdef DEBUG_TREE
3329 fprintf(stderr, "xmlNewReconciliedNs : tree == NULL\n");
3330#endif
3331 return(NULL);
3332 }
3333 if (ns == NULL) {
3334#ifdef DEBUG_TREE
3335 fprintf(stderr, "xmlNewReconciliedNs : ns == NULL\n");
3336#endif
3337 return(NULL);
3338 }
3339 /*
3340 * Search an existing namespace definition inherited.
3341 */
3342 def = xmlSearchNsByHref(doc, tree, ns->href);
3343 if (def != NULL)
3344 return(def);
3345
3346 /*
3347 * Find a close prefix which is not already in use.
3348 * Let's strip namespace prefixes longer than 20 chars !
3349 */
3350 sprintf((char *) prefix, "%.20s", ns->prefix);
3351 def = xmlSearchNs(doc, tree, prefix);
3352 while (def != NULL) {
3353 if (counter > 1000) return(NULL);
3354 sprintf((char *) prefix, "%.20s%d", ns->prefix, counter++);
3355 def = xmlSearchNs(doc, tree, prefix);
3356 }
3357
3358 /*
3359 * Ok, now we are ready to create a new one.
3360 */
3361 def = xmlNewNs(tree, ns->href, prefix);
3362 return(def);
3363}
3364
3365/**
3366 * xmlReconciliateNs
3367 * @doc: the document
3368 * @tree: a node defining the subtree to reconciliate
3369 *
3370 * This function checks that all the namespaces declared within the given
3371 * tree are properly declared. This is needed for example after Copy or Cut
3372 * and then paste operations. The subtree may still hold pointers to
3373 * namespace declarations outside the subtree or invalid/masked. As much
3374 * as possible the function try tu reuse the existing namespaces found in
3375 * the new environment. If not possible the new namespaces are redeclared
3376 * on @tree at the top of the given subtree.
3377 * Returns the number of namespace declarations created or -1 in case of error.
3378 */
3379int
3380xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
3381 xmlNsPtr *oldNs = NULL;
3382 xmlNsPtr *newNs = NULL;
3383 int sizeCache = 0;
3384 int nbCache = 0;
3385
3386 xmlNsPtr n;
3387 xmlNodePtr node = tree;
3388 xmlAttrPtr attr;
3389 int ret = 0, i;
3390
3391 while (node != NULL) {
3392 /*
3393 * Reconciliate the node namespace
3394 */
3395 if (node->ns != NULL) {
3396 /*
3397 * initialize the cache if needed
3398 */
3399 if (sizeCache == 0) {
3400 sizeCache = 10;
3401 oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3402 sizeof(xmlNsPtr));
3403 if (oldNs == NULL) {
3404 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3405 return(-1);
3406 }
3407 newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3408 sizeof(xmlNsPtr));
3409 if (newNs == NULL) {
3410 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3411 xmlFree(oldNs);
3412 return(-1);
3413 }
3414 }
3415 for (i = 0;i < nbCache;i++) {
3416 if (oldNs[i] == node->ns) {
3417 node->ns = newNs[i];
3418 break;
3419 }
3420 }
3421 if (i == nbCache) {
3422 /*
3423 * Ok we need to recreate a new namespace definition
3424 */
3425 n = xmlNewReconciliedNs(doc, tree, node->ns);
3426 if (n != NULL) { /* :-( what if else ??? */
3427 /*
3428 * check if we need to grow the cache buffers.
3429 */
3430 if (sizeCache <= nbCache) {
3431 sizeCache *= 2;
3432 oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
3433 sizeof(xmlNsPtr));
3434 if (oldNs == NULL) {
3435 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3436 xmlFree(newNs);
3437 return(-1);
3438 }
3439 newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
3440 sizeof(xmlNsPtr));
3441 if (newNs == NULL) {
3442 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3443 xmlFree(oldNs);
3444 return(-1);
3445 }
3446 }
3447 newNs[nbCache] = n;
3448 oldNs[nbCache++] = node->ns;
3449 node->ns = n;
3450 }
3451 }
3452 }
3453 /*
3454 * now check for namespace hold by attributes on the node.
3455 */
3456 attr = node->properties;
3457 while (attr != NULL) {
3458 if (attr->ns != NULL) {
3459 /*
3460 * initialize the cache if needed
3461 */
3462 if (sizeCache == 0) {
3463 sizeCache = 10;
3464 oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3465 sizeof(xmlNsPtr));
3466 if (oldNs == NULL) {
3467 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3468 return(-1);
3469 }
3470 newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3471 sizeof(xmlNsPtr));
3472 if (newNs == NULL) {
3473 fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3474 xmlFree(oldNs);
3475 return(-1);
3476 }
3477 }
3478 for (i = 0;i < nbCache;i++) {
3479 if (oldNs[i] == attr->ns) {
3480 node->ns = newNs[i];
3481 break;
3482 }
3483 }
3484 if (i == nbCache) {
3485 /*
3486 * Ok we need to recreate a new namespace definition
3487 */
3488 n = xmlNewReconciliedNs(doc, tree, attr->ns);
3489 if (n != NULL) { /* :-( what if else ??? */
3490 /*
3491 * check if we need to grow the cache buffers.
3492 */
3493 if (sizeCache <= nbCache) {
3494 sizeCache *= 2;
3495 oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
3496 sizeof(xmlNsPtr));
3497 if (oldNs == NULL) {
3498 fprintf(stderr,
3499 "xmlReconciliateNs : memory pbm\n");
3500 xmlFree(newNs);
3501 return(-1);
3502 }
3503 newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
3504 sizeof(xmlNsPtr));
3505 if (newNs == NULL) {
3506 fprintf(stderr,
3507 "xmlReconciliateNs : memory pbm\n");
3508 xmlFree(oldNs);
3509 return(-1);
3510 }
3511 }
3512 newNs[nbCache] = n;
3513 oldNs[nbCache++] = attr->ns;
3514 attr->ns = n;
3515 }
3516 }
3517 }
3518 attr = attr->next;
3519 }
3520
3521 /*
3522 * Browse the full subtree, deep first
3523 */
Daniel Veillardcf461992000-03-14 18:30:20 +00003524 if (node->children != NULL) {
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003525 /* deep first */
Daniel Veillardcf461992000-03-14 18:30:20 +00003526 node = node->children;
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003527 } else if ((node != tree) && (node->next != NULL)) {
3528 /* then siblings */
3529 node = node->next;
3530 } else if (node != tree) {
3531 /* go up to parents->next if needed */
3532 while (node != tree) {
3533 if (node->parent != NULL)
3534 node = node->parent;
3535 if ((node != tree) && (node->next != NULL)) {
3536 node = node->next;
3537 break;
3538 }
3539 if (node->parent == NULL) {
3540 node = NULL;
3541 break;
3542 }
3543 }
3544 /* exit condition */
3545 if (node == tree)
3546 node = NULL;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003547 }
3548 }
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003549 return(ret);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003550}
3551
Daniel Veillard97b58771998-10-20 06:14:16 +00003552/**
Daniel Veillard32bc74e2000-07-14 14:49:25 +00003553 * xmlHasProp:
3554 * @node: the node
3555 * @name: the attribute name
3556 *
3557 * Search an attribute associated to a node
3558 * This function also looks in DTD attribute declaration for #FIXED or
3559 * default declaration values unless DTD use has been turned off.
3560 *
3561 * Returns the attribute or the attribute declaration or NULL if
3562 * neither was found.
3563 */
3564xmlAttrPtr
3565xmlHasProp(xmlNodePtr node, const xmlChar *name) {
3566 xmlAttrPtr prop;
3567 xmlDocPtr doc;
3568
3569 if ((node == NULL) || (name == NULL)) return(NULL);
3570 /*
3571 * Check on the properties attached to the node
3572 */
3573 prop = node->properties;
3574 while (prop != NULL) {
Daniel Veillard8b5dd832000-10-01 20:28:44 +00003575 if (xmlStrEqual(prop->name, name)) {
Daniel Veillard32bc74e2000-07-14 14:49:25 +00003576 return(prop);
3577 }
3578 prop = prop->next;
3579 }
3580 if (!xmlCheckDTD) return(NULL);
3581
3582 /*
3583 * Check if there is a default declaration in the internal
3584 * or external subsets
3585 */
3586 doc = node->doc;
3587 if (doc != NULL) {
3588 xmlAttributePtr attrDecl;
3589 if (doc->intSubset != NULL) {
3590 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3591 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3592 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
3593 if (attrDecl != NULL)
3594 return((xmlAttrPtr) attrDecl);
3595 }
3596 }
3597 return(NULL);
3598}
3599
3600/**
Daniel Veillard97b58771998-10-20 06:14:16 +00003601 * xmlGetProp:
3602 * @node: the node
3603 * @name: the attribute name
3604 *
3605 * Search and get the value of an attribute associated to a node
Daniel Veillardccb09631998-10-27 06:21:04 +00003606 * This does the entity substitution.
Daniel Veillard10a2c651999-12-12 13:03:50 +00003607 * This function looks in DTD attribute declaration for #FIXED or
3608 * default declaration values unless DTD use has been turned off.
3609 *
Daniel Veillard1e346af1999-02-22 10:33:01 +00003610 * Returns the attribute value or NULL if not found.
Daniel Veillarda819dac1999-11-24 18:04:22 +00003611 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003612 */
Daniel Veillarda819dac1999-11-24 18:04:22 +00003613xmlChar *
3614xmlGetProp(xmlNodePtr node, const xmlChar *name) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00003615 xmlAttrPtr prop;
3616 xmlDocPtr doc;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003617
Daniel Veillard10a2c651999-12-12 13:03:50 +00003618 if ((node == NULL) || (name == NULL)) return(NULL);
3619 /*
3620 * Check on the properties attached to the node
3621 */
3622 prop = node->properties;
Daniel Veillard260a68f1998-08-13 03:39:55 +00003623 while (prop != NULL) {
Daniel Veillard8b5dd832000-10-01 20:28:44 +00003624 if (xmlStrEqual(prop->name, name)) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003625 xmlChar *ret;
Daniel Veillard6800ef31999-02-08 18:33:22 +00003626
Daniel Veillardcf461992000-03-14 18:30:20 +00003627 ret = xmlNodeListGetString(node->doc, prop->children, 1);
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003628 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
Daniel Veillard6800ef31999-02-08 18:33:22 +00003629 return(ret);
Daniel Veillard68178931999-02-08 18:34:36 +00003630 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003631 prop = prop->next;
3632 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00003633 if (!xmlCheckDTD) return(NULL);
3634
3635 /*
3636 * Check if there is a default declaration in the internal
3637 * or external subsets
3638 */
3639 doc = node->doc;
3640 if (doc != NULL) {
3641 xmlAttributePtr attrDecl;
3642 if (doc->intSubset != NULL) {
3643 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3644 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3645 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
Daniel Veillardf967b902000-01-17 16:06:10 +00003646 if (attrDecl != NULL)
3647 return(xmlStrdup(attrDecl->defaultValue));
Daniel Veillard10a2c651999-12-12 13:03:50 +00003648 }
3649 }
3650 return(NULL);
3651}
3652
3653/**
3654 * xmlGetNsProp:
3655 * @node: the node
3656 * @name: the attribute name
3657 * @namespace: the URI of the namespace
3658 *
3659 * Search and get the value of an attribute associated to a node
3660 * This attribute has to be anchored in the namespace specified.
3661 * This does the entity substitution.
3662 * This function looks in DTD attribute declaration for #FIXED or
3663 * default declaration values unless DTD use has been turned off.
3664 *
3665 * Returns the attribute value or NULL if not found.
3666 * It's up to the caller to free the memory.
3667 */
3668xmlChar *
3669xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) {
3670 xmlAttrPtr prop = node->properties;
3671 xmlDocPtr doc;
3672 xmlNsPtr ns;
3673
3674 if (namespace == NULL)
3675 return(xmlGetProp(node, name));
3676 while (prop != NULL) {
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00003677 /*
3678 * One need to have
3679 * - same attribute names
3680 * - and the attribute carrying that namespace
3681 * or
3682 * no namespace on the attribute and the element carrying it
3683 */
Daniel Veillard8b5dd832000-10-01 20:28:44 +00003684 if ((xmlStrEqual(prop->name, name)) &&
Daniel Veillard5cb5ab81999-12-21 15:35:29 +00003685 (((prop->ns == NULL) && (node->ns != NULL) &&
Daniel Veillard8b5dd832000-10-01 20:28:44 +00003686 (xmlStrEqual(node->ns->href, namespace))) ||
3687 ((prop->ns != NULL) && (xmlStrEqual(prop->ns->href, namespace))))) {
Daniel Veillard10a2c651999-12-12 13:03:50 +00003688 xmlChar *ret;
3689
Daniel Veillardcf461992000-03-14 18:30:20 +00003690 ret = xmlNodeListGetString(node->doc, prop->children, 1);
Daniel Veillard10a2c651999-12-12 13:03:50 +00003691 if (ret == NULL) return(xmlStrdup((xmlChar *)""));
3692 return(ret);
3693 }
3694 prop = prop->next;
3695 }
3696 if (!xmlCheckDTD) return(NULL);
3697
3698 /*
3699 * Check if there is a default declaration in the internal
3700 * or external subsets
3701 */
3702 doc = node->doc;
3703 if (doc != NULL) {
3704 xmlAttributePtr attrDecl;
3705 if (doc->intSubset != NULL) {
3706 attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3707 if ((attrDecl == NULL) && (doc->extSubset != NULL))
3708 attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
3709
3710 if (attrDecl->prefix != NULL) {
3711 /*
3712 * The DTD declaration only allows a prefix search
3713 */
3714 ns = xmlSearchNs(doc, node, attrDecl->prefix);
Daniel Veillard8b5dd832000-10-01 20:28:44 +00003715 if ((ns != NULL) && (xmlStrEqual(ns->href, namespace)))
Daniel Veillard10a2c651999-12-12 13:03:50 +00003716 return(xmlStrdup(attrDecl->defaultValue));
3717 }
3718 }
3719 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003720 return(NULL);
3721}
3722
Daniel Veillard97b58771998-10-20 06:14:16 +00003723/**
Daniel Veillardccb09631998-10-27 06:21:04 +00003724 * xmlSetProp:
Daniel Veillard97b58771998-10-20 06:14:16 +00003725 * @node: the node
3726 * @name: the attribute name
3727 * @value: the attribute value
3728 *
3729 * Set (or reset) an attribute carried by a node.
Daniel Veillard1e346af1999-02-22 10:33:01 +00003730 * Returns the attribute pointer.
Daniel Veillard260a68f1998-08-13 03:39:55 +00003731 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003732xmlAttrPtr
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003733xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003734 xmlAttrPtr prop = node->properties;
3735
3736 while (prop != NULL) {
Daniel Veillard8b5dd832000-10-01 20:28:44 +00003737 if (xmlStrEqual(prop->name, name)) {
Daniel Veillardcf461992000-03-14 18:30:20 +00003738 if (prop->children != NULL)
3739 xmlFreeNodeList(prop->children);
3740 prop->children = NULL;
Daniel Veillard51e3b151999-11-12 17:02:31 +00003741 if (value != NULL) {
3742 xmlChar *buffer;
Daniel Veillardcf461992000-03-14 18:30:20 +00003743 xmlNodePtr tmp;
3744
Daniel Veillard51e3b151999-11-12 17:02:31 +00003745 buffer = xmlEncodeEntitiesReentrant(node->doc, value);
Daniel Veillardcf461992000-03-14 18:30:20 +00003746 prop->children = xmlStringGetNodeList(node->doc, buffer);
3747 tmp = prop->children;
3748 while (tmp != NULL) {
3749 tmp->parent = (xmlNodePtr) prop;
3750 if (tmp->next == NULL)
3751 prop->last = tmp;
3752 tmp = tmp->next;
3753 }
Daniel Veillard51e3b151999-11-12 17:02:31 +00003754 xmlFree(buffer);
3755 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00003756 return(prop);
3757 }
3758 prop = prop->next;
3759 }
3760 prop = xmlNewProp(node, name, value);
3761 return(prop);
3762}
3763
Daniel Veillard97b58771998-10-20 06:14:16 +00003764/**
3765 * xmlNodeIsText:
3766 * @node: the node
3767 *
3768 * Is this node a Text node ?
Daniel Veillard1e346af1999-02-22 10:33:01 +00003769 * Returns 1 yes, 0 no
Daniel Veillard260a68f1998-08-13 03:39:55 +00003770 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003771int
3772xmlNodeIsText(xmlNodePtr node) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003773 if (node == NULL) return(0);
3774
Daniel Veillard0bef1311998-10-14 02:36:47 +00003775 if (node->type == XML_TEXT_NODE) return(1);
Daniel Veillard260a68f1998-08-13 03:39:55 +00003776 return(0);
3777}
3778
Daniel Veillard97b58771998-10-20 06:14:16 +00003779/**
Daniel Veillard3e6d2372000-03-04 11:39:43 +00003780 * xmlIsBlankNode:
3781 * @node: the node
3782 *
Daniel Veillard32bc74e2000-07-14 14:49:25 +00003783 * Checks whether this node is an empty or whitespace only
3784 * (and possibly ignorable) text-node.
3785 *
Daniel Veillard3e6d2372000-03-04 11:39:43 +00003786 * Returns 1 yes, 0 no
3787 */
3788int
3789xmlIsBlankNode(xmlNodePtr node) {
3790 xmlChar *cur;
3791 if (node == NULL) return(0);
3792
3793 if (node->type != XML_TEXT_NODE) return(0);
Daniel Veillardcd429612000-10-11 15:57:05 +00003794 if (node->content == NULL) return(1);
Daniel Veillard3e6d2372000-03-04 11:39:43 +00003795 cur = node->content;
3796 while (*cur != 0) {
3797 if (!IS_BLANK(*cur)) return(0);
3798 cur++;
3799 }
3800
3801 return(1);
3802}
3803
3804/**
Daniel Veillard1e346af1999-02-22 10:33:01 +00003805 * xmlTextConcat:
Daniel Veillard97b58771998-10-20 06:14:16 +00003806 * @node: the node
3807 * @content: the content
3808 * @len: @content lenght
3809 *
3810 * Concat the given string at the end of the existing node content
Daniel Veillard260a68f1998-08-13 03:39:55 +00003811 */
Daniel Veillard97b58771998-10-20 06:14:16 +00003812
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00003813void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003814xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00003815 if (node == NULL) return;
3816
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003817 if ((node->type != XML_TEXT_NODE) &&
3818 (node->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003819#ifdef DEBUG_TREE
Daniel Veillarddbfd6411999-12-28 16:35:14 +00003820 fprintf(stderr, "xmlTextConcat: node is not text nor cdata\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003821#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003822 return;
3823 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003824#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard260a68f1998-08-13 03:39:55 +00003825 node->content = xmlStrncat(node->content, content, len);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003826#else
3827 xmlBufferAdd(node->content, content, len);
3828#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00003829}
3830
3831/************************************************************************
3832 * *
3833 * Output : to a FILE or in memory *
3834 * *
3835 ************************************************************************/
3836
Daniel Veillard5099ae81999-04-21 20:12:07 +00003837#define BASE_BUFFER_SIZE 4000
3838
3839/**
3840 * xmlBufferCreate:
3841 *
3842 * routine to create an XML buffer.
3843 * returns the new structure.
3844 */
3845xmlBufferPtr
3846xmlBufferCreate(void) {
3847 xmlBufferPtr ret;
3848
Daniel Veillard6454aec1999-09-02 22:04:43 +00003849 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003850 if (ret == NULL) {
3851 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3852 return(NULL);
3853 }
3854 ret->use = 0;
3855 ret->size = BASE_BUFFER_SIZE;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003856 ret->alloc = xmlBufferAllocScheme;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003857 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
Daniel Veillard5099ae81999-04-21 20:12:07 +00003858 if (ret->content == NULL) {
3859 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
Daniel Veillard6454aec1999-09-02 22:04:43 +00003860 xmlFree(ret);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003861 return(NULL);
3862 }
3863 ret->content[0] = 0;
3864 return(ret);
3865}
3866
3867/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003868 * xmlBufferCreateSize:
3869 * @size: initial size of buffer
3870 *
3871 * routine to create an XML buffer.
3872 * returns the new structure.
3873 */
3874xmlBufferPtr
3875xmlBufferCreateSize(size_t size) {
3876 xmlBufferPtr ret;
3877
3878 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
3879 if (ret == NULL) {
3880 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3881 return(NULL);
3882 }
3883 ret->use = 0;
Daniel Veillard10a2c651999-12-12 13:03:50 +00003884 ret->alloc = xmlBufferAllocScheme;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003885 ret->size = (size ? size+2 : 0); /* +1 for ending null */
Daniel Veillard10a2c651999-12-12 13:03:50 +00003886 if (ret->size){
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003887 ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
3888 if (ret->content == NULL) {
3889 fprintf(stderr, "xmlBufferCreate : out of memory!\n");
3890 xmlFree(ret);
3891 return(NULL);
3892 }
3893 ret->content[0] = 0;
3894 } else
3895 ret->content = NULL;
3896 return(ret);
3897}
3898
3899/**
Daniel Veillard06047432000-04-24 11:33:38 +00003900 * xmlBufferSetAllocationScheme:
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003901 * @buf: the buffer to free
3902 * @scheme: allocation scheme to use
3903 *
3904 * Sets the allocation scheme for this buffer
3905 */
3906void
3907xmlBufferSetAllocationScheme(xmlBufferPtr buf,
3908 xmlBufferAllocationScheme scheme) {
3909 if (buf == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003910#ifdef DEBUG_BUFFER
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003911 fprintf(stderr, "xmlBufferSetAllocationScheme: buf == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003912#endif
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003913 return;
3914 }
3915
3916 buf->alloc = scheme;
3917}
3918
3919/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00003920 * xmlBufferFree:
3921 * @buf: the buffer to free
3922 *
3923 * Frees an XML buffer.
3924 */
3925void
3926xmlBufferFree(xmlBufferPtr buf) {
3927 if (buf == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003928#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00003929 fprintf(stderr, "xmlBufferFree: buf == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00003930#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00003931 return;
3932 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003933 if (buf->content != NULL) {
3934#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00003935 memset(buf->content, -1, BASE_BUFFER_SIZE);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00003936#else
3937 memset(buf->content, -1, buf->size);
3938#endif
Daniel Veillard6454aec1999-09-02 22:04:43 +00003939 xmlFree(buf->content);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003940 }
3941 memset(buf, -1, sizeof(xmlBuffer));
Daniel Veillard6454aec1999-09-02 22:04:43 +00003942 xmlFree(buf);
Daniel Veillard5099ae81999-04-21 20:12:07 +00003943}
3944
3945/**
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003946 * xmlBufferEmpty:
3947 * @buf: the buffer
3948 *
3949 * empty a buffer.
3950 */
3951void
3952xmlBufferEmpty(xmlBufferPtr buf) {
Daniel Veillard4fb87ee2000-09-19 12:25:59 +00003953 if (buf->content == NULL) return;
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003954 buf->use = 0;
3955 memset(buf->content, -1, buf->size);/* just for debug */
3956}
3957
3958/**
3959 * xmlBufferShrink:
3960 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003961 * @len: the number of xmlChar to remove
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003962 *
3963 * Remove the beginning of an XML buffer.
3964 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003965 * Returns the number of xmlChar removed, or -1 in case of failure.
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003966 */
3967int
Daniel Veillard4b0755c2000-09-25 14:26:28 +00003968xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003969 if (len == 0) return(0);
3970 if (len > buf->use) return(-1);
3971
3972 buf->use -= len;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00003973 memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00003974
3975 buf->content[buf->use] = 0;
3976 return(len);
3977}
3978
3979/**
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003980 * xmlBufferGrow:
3981 * @buf: the buffer
3982 * @len: the minimum free sie to allocate
3983 *
3984 * Grow the available space of an XML buffer.
3985 *
3986 * Returns the new available space or -1 in case of error
3987 */
3988int
Daniel Veillard4b0755c2000-09-25 14:26:28 +00003989xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003990 int size;
3991 xmlChar *newbuf;
3992
3993 if (len <= buf->use) return(0);
3994
Daniel Veillardbe803962000-06-28 23:40:59 +00003995 size = buf->use + len + 100;
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003996
Daniel Veillard32bc74e2000-07-14 14:49:25 +00003997 newbuf = (xmlChar *) xmlRealloc(buf->content, size);
Daniel Veillard496a1cf2000-05-03 14:20:55 +00003998 if (newbuf == NULL) return(-1);
3999 buf->content = newbuf;
4000 buf->size = size;
4001 return(buf->size - buf->use);
4002}
4003
4004/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00004005 * xmlBufferDump:
4006 * @file: the file output
4007 * @buf: the buffer to dump
4008 *
4009 * Dumps an XML buffer to a FILE *.
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004010 * Returns the number of xmlChar written
Daniel Veillard5099ae81999-04-21 20:12:07 +00004011 */
4012int
4013xmlBufferDump(FILE *file, xmlBufferPtr buf) {
4014 int ret;
4015
4016 if (buf == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004017#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00004018 fprintf(stderr, "xmlBufferDump: buf == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004019#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00004020 return(0);
4021 }
4022 if (buf->content == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004023#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00004024 fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004025#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00004026 return(0);
4027 }
4028 if (file == NULL) file = stdout;
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004029 ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
Daniel Veillard5099ae81999-04-21 20:12:07 +00004030 return(ret);
4031}
4032
4033/**
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004034 * xmlBufferContent:
4035 * @buf: the buffer to resize
4036 *
4037 * Returns the internal content
4038 */
4039
4040const xmlChar*
4041xmlBufferContent(const xmlBufferPtr buf)
4042{
4043 if(!buf)
4044 return NULL;
4045
4046 return buf->content;
4047}
4048
4049/**
4050 * xmlBufferLength:
4051 * @buf: the buffer
4052 *
4053 * Returns the length of data in the internal content
4054 */
4055
4056int
4057xmlBufferLength(const xmlBufferPtr buf)
4058{
4059 if(!buf)
4060 return 0;
4061
4062 return buf->use;
4063}
4064
4065/**
4066 * xmlBufferResize:
4067 * @buf: the buffer to resize
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004068 * @size: the desired size
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004069 *
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004070 * Resize a buffer to accomodate minimum size of @size.
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004071 *
4072 * Returns 0 in case of problems, 1 otherwise
4073 */
4074int
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004075xmlBufferResize(xmlBufferPtr buf, unsigned int size)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004076{
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004077 unsigned int newSize;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004078 xmlChar* rebuf = NULL;
4079
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004080 /*take care of empty case*/
4081 newSize = (buf->size ? buf->size*2 : size);
4082
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004083 /* Don't resize if we don't have to */
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004084 if (size < buf->size)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004085 return 1;
4086
4087 /* figure out new size */
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004088 switch (buf->alloc){
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004089 case XML_BUFFER_ALLOC_DOUBLEIT:
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004090 while (size > newSize) newSize *= 2;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004091 break;
4092 case XML_BUFFER_ALLOC_EXACT:
4093 newSize = size+10;
4094 break;
4095 default:
4096 newSize = size+10;
4097 break;
4098 }
4099
4100 if (buf->content == NULL)
4101 rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
4102 else
4103 rebuf = (xmlChar *) xmlRealloc(buf->content,
4104 newSize * sizeof(xmlChar));
4105 if (rebuf == NULL) {
4106 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
4107 return 0;
4108 }
4109 buf->content = rebuf;
4110 buf->size = newSize;
4111
4112 return 1;
4113}
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004114
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004115/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00004116 * xmlBufferAdd:
4117 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004118 * @str: the xmlChar string
4119 * @len: the number of xmlChar to add
Daniel Veillard5099ae81999-04-21 20:12:07 +00004120 *
Daniel Veillard10a2c651999-12-12 13:03:50 +00004121 * Add a string range to an XML buffer. if len == -1, the lenght of
4122 * str is recomputed.
Daniel Veillard5099ae81999-04-21 20:12:07 +00004123 */
4124void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004125xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004126 unsigned int needSize;
Daniel Veillard5099ae81999-04-21 20:12:07 +00004127
4128 if (str == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004129#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00004130 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004131#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00004132 return;
4133 }
Daniel Veillard10a2c651999-12-12 13:03:50 +00004134 if (len < -1) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004135#ifdef DEBUG_BUFFER
Daniel Veillard10a2c651999-12-12 13:03:50 +00004136 fprintf(stderr, "xmlBufferAdd: len < 0\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004137#endif
Daniel Veillard10a2c651999-12-12 13:03:50 +00004138 return;
4139 }
4140 if (len == 0) return;
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004141
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004142 if (len < 0)
Daniel Veillardcf461992000-03-14 18:30:20 +00004143 len = xmlStrlen(str);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004144
Daniel Veillarde2d034d1999-07-27 19:52:06 +00004145 if (len <= 0) return;
Daniel Veillard5099ae81999-04-21 20:12:07 +00004146
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004147 needSize = buf->use + len + 2;
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004148 if (needSize > buf->size){
4149 if (!xmlBufferResize(buf, needSize)){
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004150 fprintf(stderr, "xmlBufferAdd : out of memory!\n");
4151 return;
4152 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004153 }
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004154
4155 memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
Daniel Veillarde2d034d1999-07-27 19:52:06 +00004156 buf->use += len;
4157 buf->content[buf->use] = 0;
Daniel Veillard5099ae81999-04-21 20:12:07 +00004158}
4159
4160/**
Daniel Veillardbe803962000-06-28 23:40:59 +00004161 * xmlBufferAddHead:
4162 * @buf: the buffer
4163 * @str: the xmlChar string
4164 * @len: the number of xmlChar to add
4165 *
4166 * Add a string range to the beginning of an XML buffer.
4167 * if len == -1, the lenght of @str is recomputed.
4168 */
4169void
4170xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004171 unsigned int needSize;
Daniel Veillardbe803962000-06-28 23:40:59 +00004172
4173 if (str == NULL) {
4174#ifdef DEBUG_BUFFER
4175 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
4176#endif
4177 return;
4178 }
4179 if (len < -1) {
4180#ifdef DEBUG_BUFFER
4181 fprintf(stderr, "xmlBufferAdd: len < 0\n");
4182#endif
4183 return;
4184 }
4185 if (len == 0) return;
4186
4187 if (len < 0)
4188 len = xmlStrlen(str);
4189
4190 if (len <= 0) return;
4191
4192 needSize = buf->use + len + 2;
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004193 if (needSize > buf->size){
4194 if (!xmlBufferResize(buf, needSize)){
Daniel Veillardbe803962000-06-28 23:40:59 +00004195 fprintf(stderr, "xmlBufferAddHead : out of memory!\n");
4196 return;
4197 }
4198 }
4199
4200 memmove(&buf->content[len], &buf->content[0], buf->use * sizeof(xmlChar));
4201 memmove(&buf->content[0], str, len * sizeof(xmlChar));
4202 buf->use += len;
4203 buf->content[buf->use] = 0;
4204}
4205
4206/**
Daniel Veillard5099ae81999-04-21 20:12:07 +00004207 * xmlBufferCat:
4208 * @buf: the buffer to dump
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004209 * @str: the xmlChar string
Daniel Veillard5099ae81999-04-21 20:12:07 +00004210 *
4211 * Append a zero terminated string to an XML buffer.
4212 */
4213void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004214xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004215 if (str != NULL)
4216 xmlBufferAdd(buf, str, -1);
Daniel Veillard5099ae81999-04-21 20:12:07 +00004217}
4218
4219/**
4220 * xmlBufferCCat:
4221 * @buf: the buffer to dump
4222 * @str: the C char string
4223 *
4224 * Append a zero terminated C string to an XML buffer.
4225 */
4226void
4227xmlBufferCCat(xmlBufferPtr buf, const char *str) {
4228 const char *cur;
4229
4230 if (str == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004231#ifdef DEBUG_BUFFER
Daniel Veillard5099ae81999-04-21 20:12:07 +00004232 fprintf(stderr, "xmlBufferAdd: str == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004233#endif
Daniel Veillard5099ae81999-04-21 20:12:07 +00004234 return;
4235 }
4236 for (cur = str;*cur != 0;cur++) {
4237 if (buf->use + 10 >= buf->size) {
Daniel Veillard4b0755c2000-09-25 14:26:28 +00004238 if (!xmlBufferResize(buf, buf->use+10)){
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004239 fprintf(stderr, "xmlBufferCCat : out of memory!\n");
4240 return;
4241 }
4242 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004243 buf->content[buf->use++] = *cur;
4244 }
4245}
Daniel Veillard260a68f1998-08-13 03:39:55 +00004246
Daniel Veillard97b58771998-10-20 06:14:16 +00004247/**
4248 * xmlBufferWriteCHAR:
Daniel Veillard5099ae81999-04-21 20:12:07 +00004249 * @buf: the XML buffer
Daniel Veillard97b58771998-10-20 06:14:16 +00004250 * @string: the string to add
4251 *
4252 * routine which manage and grows an output buffer. This one add
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004253 * xmlChars at the end of the buffer.
Daniel Veillard97b58771998-10-20 06:14:16 +00004254 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004255void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004256xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004257 xmlBufferCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004258}
4259
Daniel Veillard97b58771998-10-20 06:14:16 +00004260/**
4261 * xmlBufferWriteChar:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004262 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004263 * @string: the string to add
4264 *
4265 * routine which manage and grows an output buffer. This one add
4266 * C chars at the end of the array.
4267 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004268void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004269xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
4270 xmlBufferCCat(buf, string);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004271}
4272
Daniel Veillard5099ae81999-04-21 20:12:07 +00004273
Daniel Veillard97b58771998-10-20 06:14:16 +00004274/**
Daniel Veillard011b63c1999-06-02 17:44:04 +00004275 * xmlBufferWriteQuotedString:
4276 * @buf: the XML buffer output
4277 * @string: the string to add
4278 *
4279 * routine which manage and grows an output buffer. This one writes
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004280 * a quoted or double quoted xmlChar string, checking first if it holds
Daniel Veillard011b63c1999-06-02 17:44:04 +00004281 * quote or double-quotes internally
4282 */
4283void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004284xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
Daniel Veillardb96e6431999-08-29 21:02:19 +00004285 if (xmlStrchr(string, '"')) {
4286 if (xmlStrchr(string, '\'')) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004287#ifdef DEBUG_BUFFER
Daniel Veillard011b63c1999-06-02 17:44:04 +00004288 fprintf(stderr,
4289 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004290#endif
Daniel Veillard011b63c1999-06-02 17:44:04 +00004291 }
4292 xmlBufferCCat(buf, "'");
4293 xmlBufferCat(buf, string);
4294 xmlBufferCCat(buf, "'");
4295 } else {
4296 xmlBufferCCat(buf, "\"");
4297 xmlBufferCat(buf, string);
4298 xmlBufferCCat(buf, "\"");
4299 }
4300}
4301
4302
Daniel Veillardbe803962000-06-28 23:40:59 +00004303/************************************************************************
4304 * *
4305 * Dumping XML tree content to a simple buffer *
4306 * *
4307 ************************************************************************/
4308
Daniel Veillardb656ebe2000-09-22 13:51:48 +00004309void
Daniel Veillardcf461992000-03-14 18:30:20 +00004310xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4311 int format);
4312static void
4313xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4314 int format);
4315void
4316htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur);
4317
Daniel Veillard011b63c1999-06-02 17:44:04 +00004318/**
Daniel Veillard97b58771998-10-20 06:14:16 +00004319 * xmlGlobalNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004320 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004321 * @cur: a namespace
4322 *
4323 * Dump a global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004324 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004325static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004326xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004327 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004328#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004329 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004330#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004331 return;
4332 }
4333 if (cur->type == XML_GLOBAL_NAMESPACE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004334 xmlBufferWriteChar(buf, "<?namespace");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004335 if (cur->href != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004336 xmlBufferWriteChar(buf, " href=");
4337 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004338 }
4339 if (cur->prefix != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004340 xmlBufferWriteChar(buf, " AS=");
4341 xmlBufferWriteQuotedString(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004342 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004343 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004344 }
4345}
4346
Daniel Veillard97b58771998-10-20 06:14:16 +00004347/**
4348 * xmlGlobalNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004349 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004350 * @cur: the first namespace
4351 *
4352 * Dump a list of global Namespace, this is the old version based on PIs.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004353 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004354static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004355xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004356 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004357 xmlGlobalNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004358 cur = cur->next;
4359 }
4360}
4361
Daniel Veillard97b58771998-10-20 06:14:16 +00004362/**
4363 * xmlNsDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004364 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004365 * @cur: a namespace
4366 *
Daniel Veillard260a68f1998-08-13 03:39:55 +00004367 * Dump a local Namespace definition.
Daniel Veillard97b58771998-10-20 06:14:16 +00004368 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004369 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004370static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004371xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004372 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004373#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004374 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004375#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004376 return;
4377 }
4378 if (cur->type == XML_LOCAL_NAMESPACE) {
4379 /* Within the context of an element attributes */
4380 if (cur->prefix != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004381 xmlBufferWriteChar(buf, " xmlns:");
4382 xmlBufferWriteCHAR(buf, cur->prefix);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004383 } else
Daniel Veillard5099ae81999-04-21 20:12:07 +00004384 xmlBufferWriteChar(buf, " xmlns");
Daniel Veillard011b63c1999-06-02 17:44:04 +00004385 xmlBufferWriteChar(buf, "=");
4386 xmlBufferWriteQuotedString(buf, cur->href);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004387 }
4388}
4389
Daniel Veillard97b58771998-10-20 06:14:16 +00004390/**
4391 * xmlNsListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004392 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004393 * @cur: the first namespace
4394 *
4395 * Dump a list of local Namespace definitions.
4396 * Should be called in the context of attributes dumps.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004397 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004398static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004399xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004400 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004401 xmlNsDump(buf, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004402 cur = cur->next;
4403 }
4404}
4405
Daniel Veillard97b58771998-10-20 06:14:16 +00004406/**
4407 * xmlDtdDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004408 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004409 * @doc: the document
4410 *
4411 * Dump the XML document DTD, if any.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004412 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004413static void
Daniel Veillardcf461992000-03-14 18:30:20 +00004414xmlDtdDump(xmlBufferPtr buf, xmlDtdPtr dtd) {
4415 if (dtd == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004416#ifdef DEBUG_TREE
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004417 fprintf(stderr, "xmlDtdDump : no internal subset\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004418#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004419 return;
4420 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004421 xmlBufferWriteChar(buf, "<!DOCTYPE ");
Daniel Veillardcf461992000-03-14 18:30:20 +00004422 xmlBufferWriteCHAR(buf, dtd->name);
4423 if (dtd->ExternalID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004424 xmlBufferWriteChar(buf, " PUBLIC ");
Daniel Veillardcf461992000-03-14 18:30:20 +00004425 xmlBufferWriteQuotedString(buf, dtd->ExternalID);
Daniel Veillard011b63c1999-06-02 17:44:04 +00004426 xmlBufferWriteChar(buf, " ");
Daniel Veillardcf461992000-03-14 18:30:20 +00004427 xmlBufferWriteQuotedString(buf, dtd->SystemID);
4428 } else if (dtd->SystemID != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004429 xmlBufferWriteChar(buf, " SYSTEM ");
Daniel Veillardcf461992000-03-14 18:30:20 +00004430 xmlBufferWriteQuotedString(buf, dtd->SystemID);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004431 }
Daniel Veillardcf461992000-03-14 18:30:20 +00004432 if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
4433 (dtd->attributes == NULL) && (dtd->notations == NULL)) {
4434 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004435 return;
4436 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004437 xmlBufferWriteChar(buf, " [\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00004438 xmlNodeListDump(buf, dtd->doc, dtd->children, -1, 0);
4439#if 0
4440 if (dtd->entities != NULL)
4441 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) dtd->entities);
4442 if (dtd->notations != NULL)
4443 xmlDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations);
4444 if (dtd->elements != NULL)
4445 xmlDumpElementTable(buf, (xmlElementTablePtr) dtd->elements);
4446 if (dtd->attributes != NULL)
4447 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) dtd->attributes);
4448#endif
4449 xmlBufferWriteChar(buf, "]>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004450}
4451
Daniel Veillard97b58771998-10-20 06:14:16 +00004452/**
4453 * xmlAttrDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004454 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004455 * @doc: the document
4456 * @cur: the attribute pointer
4457 *
4458 * Dump an XML attribute
Daniel Veillard260a68f1998-08-13 03:39:55 +00004459 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004460static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004461xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004462 xmlChar *value;
Daniel Veillardccb09631998-10-27 06:21:04 +00004463
Daniel Veillard260a68f1998-08-13 03:39:55 +00004464 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004465#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004466 fprintf(stderr, "xmlAttrDump : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004467#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004468 return;
4469 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004470 xmlBufferWriteChar(buf, " ");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004471 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
4472 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4473 xmlBufferWriteChar(buf, ":");
4474 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004475 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillardcf461992000-03-14 18:30:20 +00004476 value = xmlNodeListGetString(doc, cur->children, 0);
Daniel Veillardccb09631998-10-27 06:21:04 +00004477 if (value) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004478 xmlBufferWriteChar(buf, "=");
4479 xmlBufferWriteQuotedString(buf, value);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004480 xmlFree(value);
Daniel Veillard726c7e31999-02-08 15:13:10 +00004481 } else {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004482 xmlBufferWriteChar(buf, "=\"\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004483 }
4484}
4485
Daniel Veillard97b58771998-10-20 06:14:16 +00004486/**
4487 * xmlAttrListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004488 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004489 * @doc: the document
4490 * @cur: the first attribute pointer
4491 *
4492 * Dump a list of XML attributes
Daniel Veillard260a68f1998-08-13 03:39:55 +00004493 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004494static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004495xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004496 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004497#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004498 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004499#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004500 return;
4501 }
4502 while (cur != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004503 xmlAttrDump(buf, doc, cur);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004504 cur = cur->next;
4505 }
4506}
4507
Daniel Veillard260a68f1998-08-13 03:39:55 +00004508
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004509
Daniel Veillard97b58771998-10-20 06:14:16 +00004510/**
4511 * xmlNodeListDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004512 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004513 * @doc: the document
4514 * @cur: the first node
Daniel Veillardcf461992000-03-14 18:30:20 +00004515 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004516 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00004517 *
4518 * Dump an XML node list, recursive behaviour,children are printed too.
4519 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004520static void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004521xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4522 int format) {
4523 int i;
Daniel Veillardccb09631998-10-27 06:21:04 +00004524
Daniel Veillard260a68f1998-08-13 03:39:55 +00004525 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004526#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004527 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004528#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004529 return;
4530 }
4531 while (cur != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004532 if ((format) && (xmlIndentTreeOutput) &&
4533 (cur->type == XML_ELEMENT_NODE))
4534 for (i = 0;i < level;i++)
4535 xmlBufferWriteChar(buf, " ");
4536 xmlNodeDump(buf, doc, cur, level, format);
4537 if (format) {
4538 xmlBufferWriteChar(buf, "\n");
Daniel Veillardccb09631998-10-27 06:21:04 +00004539 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004540 cur = cur->next;
4541 }
4542}
4543
Daniel Veillard97b58771998-10-20 06:14:16 +00004544/**
Daniel Veillardccb09631998-10-27 06:21:04 +00004545 * xmlNodeDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004546 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004547 * @doc: the document
4548 * @cur: the current node
Daniel Veillardcf461992000-03-14 18:30:20 +00004549 * @level: the imbrication level for indenting
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004550 * @format: is formatting allowed
Daniel Veillard97b58771998-10-20 06:14:16 +00004551 *
4552 * Dump an XML node, recursive behaviour,children are printed too.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004553 */
Daniel Veillardb656ebe2000-09-22 13:51:48 +00004554void
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004555xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4556 int format) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004557 int i;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004558 xmlNodePtr tmp;
Daniel Veillard260a68f1998-08-13 03:39:55 +00004559
4560 if (cur == NULL) {
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004561#ifdef DEBUG_TREE
Daniel Veillard260a68f1998-08-13 03:39:55 +00004562 fprintf(stderr, "xmlNodeDump : node == NULL\n");
Daniel Veillardad8f99d2000-01-15 14:20:03 +00004563#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00004564 return;
4565 }
Daniel Veillardcf461992000-03-14 18:30:20 +00004566 if (cur->type == XML_DTD_NODE) {
4567 xmlDtdDump(buf, (xmlDtdPtr) cur);
4568 return;
4569 }
4570 if (cur->type == XML_ELEMENT_DECL) {
4571 xmlDumpElementDecl(buf, (xmlElementPtr) cur);
4572 return;
4573 }
4574 if (cur->type == XML_ATTRIBUTE_DECL) {
4575 xmlDumpAttributeDecl(buf, (xmlAttributePtr) cur);
4576 return;
4577 }
4578 if (cur->type == XML_ENTITY_DECL) {
4579 xmlDumpEntityDecl(buf, (xmlEntityPtr) cur);
4580 return;
4581 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00004582 if (cur->type == XML_TEXT_NODE) {
Daniel Veillard14fff061999-06-22 21:49:07 +00004583 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004584 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00004585
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004586#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00004587 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004588#else
4589 buffer = xmlEncodeEntitiesReentrant(doc,
4590 xmlBufferContent(cur->content));
4591#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00004592 if (buffer != NULL) {
4593 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004594 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00004595 }
4596 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004597 return;
4598 }
Daniel Veillardb96e6431999-08-29 21:02:19 +00004599 if (cur->type == XML_PI_NODE) {
4600 if (cur->content != NULL) {
4601 xmlBufferWriteChar(buf, "<?");
4602 xmlBufferWriteCHAR(buf, cur->name);
4603 if (cur->content != NULL) {
4604 xmlBufferWriteChar(buf, " ");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004605#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb96e6431999-08-29 21:02:19 +00004606 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004607#else
4608 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4609#endif
Daniel Veillardb96e6431999-08-29 21:02:19 +00004610 }
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004611 xmlBufferWriteChar(buf, "?>");
Daniel Veillardcf461992000-03-14 18:30:20 +00004612 } else {
4613 xmlBufferWriteChar(buf, "<?");
4614 xmlBufferWriteCHAR(buf, cur->name);
4615 xmlBufferWriteChar(buf, "?>");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004616 }
4617 return;
4618 }
Daniel Veillard0bef1311998-10-14 02:36:47 +00004619 if (cur->type == XML_COMMENT_NODE) {
Daniel Veillard260a68f1998-08-13 03:39:55 +00004620 if (cur->content != NULL) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004621 xmlBufferWriteChar(buf, "<!--");
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004622#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard5099ae81999-04-21 20:12:07 +00004623 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004624#else
4625 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4626#endif
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004627 xmlBufferWriteChar(buf, "-->");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004628 }
4629 return;
4630 }
Daniel Veillardccb09631998-10-27 06:21:04 +00004631 if (cur->type == XML_ENTITY_REF_NODE) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004632 xmlBufferWriteChar(buf, "&");
4633 xmlBufferWriteCHAR(buf, cur->name);
4634 xmlBufferWriteChar(buf, ";");
Daniel Veillardccb09631998-10-27 06:21:04 +00004635 return;
4636 }
Daniel Veillardb05deb71999-08-10 19:04:08 +00004637 if (cur->type == XML_CDATA_SECTION_NODE) {
4638 xmlBufferWriteChar(buf, "<![CDATA[");
4639 if (cur->content != NULL)
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004640#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillardb05deb71999-08-10 19:04:08 +00004641 xmlBufferWriteCHAR(buf, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004642#else
4643 xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4644#endif
Daniel Veillardb05deb71999-08-10 19:04:08 +00004645 xmlBufferWriteChar(buf, "]]>");
4646 return;
4647 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004648
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004649 if (format == 1) {
Daniel Veillardcf461992000-03-14 18:30:20 +00004650 tmp = cur->children;
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004651 while (tmp != NULL) {
4652 if ((tmp->type == XML_TEXT_NODE) ||
4653 (tmp->type == XML_ENTITY_REF_NODE)) {
4654 format = 0;
4655 break;
4656 }
4657 tmp = tmp->next;
4658 }
4659 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004660 xmlBufferWriteChar(buf, "<");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004661 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004662 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4663 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004664 }
4665
Daniel Veillard5099ae81999-04-21 20:12:07 +00004666 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004667 if (cur->nsDef)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004668 xmlNsListDump(buf, cur->nsDef);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004669 if (cur->properties != NULL)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004670 xmlAttrListDump(buf, doc, cur->properties);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004671
Daniel Veillardcf461992000-03-14 18:30:20 +00004672 if ((cur->content == NULL) && (cur->children == NULL) &&
Daniel Veillarde41f2b72000-01-30 20:00:07 +00004673 (!xmlSaveNoEmptyTags)) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004674 xmlBufferWriteChar(buf, "/>");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004675 return;
4676 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004677 xmlBufferWriteChar(buf, ">");
Daniel Veillard14fff061999-06-22 21:49:07 +00004678 if (cur->content != NULL) {
Daniel Veillarddd6b3671999-09-23 22:19:22 +00004679 xmlChar *buffer;
Daniel Veillard14fff061999-06-22 21:49:07 +00004680
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004681#ifndef XML_USE_BUFFER_CONTENT
Daniel Veillard14fff061999-06-22 21:49:07 +00004682 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
Daniel Veillardf5c2c871999-12-01 09:51:45 +00004683#else
4684 buffer = xmlEncodeEntitiesReentrant(doc,
4685 xmlBufferContent(cur->content));
4686#endif
Daniel Veillard14fff061999-06-22 21:49:07 +00004687 if (buffer != NULL) {
4688 xmlBufferWriteCHAR(buf, buffer);
Daniel Veillard6454aec1999-09-02 22:04:43 +00004689 xmlFree(buffer);
Daniel Veillard14fff061999-06-22 21:49:07 +00004690 }
4691 }
Daniel Veillardcf461992000-03-14 18:30:20 +00004692 if (cur->children != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004693 if (format) xmlBufferWriteChar(buf, "\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00004694 xmlNodeListDump(buf, doc, cur->children,
Daniel Veillard3e6d2372000-03-04 11:39:43 +00004695 (level >= 0?level+1:-1), format);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004696 if ((xmlIndentTreeOutput) && (format))
4697 for (i = 0;i < level;i++)
4698 xmlBufferWriteChar(buf, " ");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004699 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004700 xmlBufferWriteChar(buf, "</");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004701 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00004702 xmlBufferWriteCHAR(buf, cur->ns->prefix);
4703 xmlBufferWriteChar(buf, ":");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004704 }
4705
Daniel Veillard5099ae81999-04-21 20:12:07 +00004706 xmlBufferWriteCHAR(buf, cur->name);
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004707 xmlBufferWriteChar(buf, ">");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004708}
4709
Daniel Veillard97b58771998-10-20 06:14:16 +00004710/**
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004711 * xmlElemDump:
Daniel Veillard06047432000-04-24 11:33:38 +00004712 * @f: the FILE * for the output
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004713 * @doc: the document
4714 * @cur: the current node
4715 *
4716 * Dump an XML/HTML node, recursive behaviour,children are printed too.
4717 */
4718void
4719xmlElemDump(FILE *f, xmlDocPtr doc, xmlNodePtr cur) {
4720 xmlBufferPtr buf;
4721
4722 if (cur == NULL) {
4723#ifdef DEBUG_TREE
4724 fprintf(stderr, "xmlElemDump : cur == NULL\n");
4725#endif
4726 return;
4727 }
4728 if (doc == NULL) {
4729#ifdef DEBUG_TREE
4730 fprintf(stderr, "xmlElemDump : doc == NULL\n");
4731#endif
4732 }
4733 buf = xmlBufferCreate();
4734 if (buf == NULL) return;
4735 if ((doc != NULL) &&
4736 (doc->type == XML_HTML_DOCUMENT_NODE)) {
Daniel Veillard361d8452000-04-03 19:48:13 +00004737#ifdef LIBXML_HTML_ENABLED
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004738 htmlNodeDump(buf, doc, cur);
Daniel Veillard361d8452000-04-03 19:48:13 +00004739#else
4740 printf("HTML support not compiled in\n");
4741#endif /* LIBXML_HTML_ENABLED */
Daniel Veillarddbfd6411999-12-28 16:35:14 +00004742 } else
4743 xmlNodeDump(buf, doc, cur, 0, 1);
4744 xmlBufferDump(f, buf);
4745 xmlBufferFree(buf);
4746}
4747
4748/**
Daniel Veillard97b58771998-10-20 06:14:16 +00004749 * xmlDocContentDump:
Daniel Veillard011b63c1999-06-02 17:44:04 +00004750 * @buf: the XML buffer output
Daniel Veillard97b58771998-10-20 06:14:16 +00004751 * @cur: the document
4752 *
4753 * Dump an XML document.
Daniel Veillard260a68f1998-08-13 03:39:55 +00004754 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00004755static void
Daniel Veillard5099ae81999-04-21 20:12:07 +00004756xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
Daniel Veillardbe70ff71999-07-05 16:50:46 +00004757 xmlBufferWriteChar(buf, "<?xml version=");
4758 if (cur->version != NULL)
4759 xmlBufferWriteQuotedString(buf, cur->version);
4760 else
4761 xmlBufferWriteChar(buf, "\"1.0\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004762 if (cur->encoding != NULL) {
Daniel Veillard011b63c1999-06-02 17:44:04 +00004763 xmlBufferWriteChar(buf, " encoding=");
4764 xmlBufferWriteQuotedString(buf, cur->encoding);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004765 }
4766 switch (cur->standalone) {
4767 case 0:
Daniel Veillard5099ae81999-04-21 20:12:07 +00004768 xmlBufferWriteChar(buf, " standalone=\"no\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004769 break;
4770 case 1:
Daniel Veillard5099ae81999-04-21 20:12:07 +00004771 xmlBufferWriteChar(buf, " standalone=\"yes\"");
Daniel Veillard260a68f1998-08-13 03:39:55 +00004772 break;
4773 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00004774 xmlBufferWriteChar(buf, "?>\n");
Daniel Veillardcf461992000-03-14 18:30:20 +00004775 if (cur->children != NULL) {
4776 xmlNodePtr child = cur->children;
Daniel Veillardb96e6431999-08-29 21:02:19 +00004777
Daniel Veillard260a68f1998-08-13 03:39:55 +00004778 /* global namespace definitions, the old way */
4779 if (oldXMLWDcompatibility)
Daniel Veillard5099ae81999-04-21 20:12:07 +00004780 xmlGlobalNsListDump(buf, cur->oldNs);
Daniel Veillard260a68f1998-08-13 03:39:55 +00004781 else
4782 xmlUpgradeOldNs(cur);
Daniel Veillardb96e6431999-08-29 21:02:19 +00004783
4784 while (child != NULL) {
Daniel Veillard7d2c2761999-10-11 15:09:51 +00004785 xmlNodeDump(buf, cur, child, 0, 1);
4786 xmlBufferWriteChar(buf, "\n");
Daniel Veillardb96e6431999-08-29 21:02:19 +00004787 child = child->next;
4788 }
Daniel Veillard260a68f1998-08-13 03:39:55 +00004789 }
4790}
4791
Daniel Veillardbe803962000-06-28 23:40:59 +00004792/************************************************************************
4793 * *
4794 * Dumping XML tree content to an I/O output buffer *
4795 * *
4796 ************************************************************************/
4797
Daniel Veillardb656ebe2000-09-22 13:51:48 +00004798void
Daniel Veillardbe803962000-06-28 23:40:59 +00004799xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
4800 int level, int format, const char *encoding);
4801static void
4802xmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
4803 int level, int format, const char *encoding);
4804/**
4805 * xmlGlobalNsDumpOutput:
4806 * @buf: the XML buffer output
4807 * @cur: a namespace
4808 *
4809 * Dump a global Namespace, this is the old version based on PIs.
4810 */
4811static void
4812xmlGlobalNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
4813 if (cur == NULL) {
4814#ifdef DEBUG_TREE
4815 fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
4816#endif
4817 return;
4818 }
4819 if (cur->type == XML_GLOBAL_NAMESPACE) {
4820 xmlOutputBufferWriteString(buf, "<?namespace");
4821 if (cur->href != NULL) {
4822 xmlOutputBufferWriteString(buf, " href=");
4823 xmlBufferWriteQuotedString(buf->buffer, cur->href);
4824 }
4825 if (cur->prefix != NULL) {
4826 xmlOutputBufferWriteString(buf, " AS=");
4827 xmlBufferWriteQuotedString(buf->buffer, cur->prefix);
4828 }
4829 xmlOutputBufferWriteString(buf, "?>\n");
4830 }
4831}
4832
4833/**
4834 * xmlGlobalNsListDumpOutput:
4835 * @buf: the XML buffer output
4836 * @cur: the first namespace
4837 *
4838 * Dump a list of global Namespace, this is the old version based on PIs.
4839 */
4840static void
4841xmlGlobalNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
4842 while (cur != NULL) {
4843 xmlGlobalNsDumpOutput(buf, cur);
4844 cur = cur->next;
4845 }
4846}
4847
4848/**
4849 * xmlNsDumpOutput:
4850 * @buf: the XML buffer output
4851 * @cur: a namespace
4852 *
4853 * Dump a local Namespace definition.
4854 * Should be called in the context of attributes dumps.
4855 */
4856static void
4857xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
4858 if (cur == NULL) {
4859#ifdef DEBUG_TREE
4860 fprintf(stderr, "xmlNsDump : Ns == NULL\n");
4861#endif
4862 return;
4863 }
Daniel Veillarde0854c32000-08-27 21:12:29 +00004864 if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) {
Daniel Veillardbe803962000-06-28 23:40:59 +00004865 /* Within the context of an element attributes */
4866 if (cur->prefix != NULL) {
4867 xmlOutputBufferWriteString(buf, " xmlns:");
4868 xmlOutputBufferWriteString(buf, (const char *)cur->prefix);
4869 } else
4870 xmlOutputBufferWriteString(buf, " xmlns");
4871 xmlOutputBufferWriteString(buf, "=");
4872 xmlBufferWriteQuotedString(buf->buffer, cur->href);
4873 }
4874}
4875
4876/**
4877 * xmlNsListDumpOutput:
4878 * @buf: the XML buffer output
4879 * @cur: the first namespace
4880 *
4881 * Dump a list of local Namespace definitions.
4882 * Should be called in the context of attributes dumps.
4883 */
4884static void
4885xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
4886 while (cur != NULL) {
4887 xmlNsDumpOutput(buf, cur);
4888 cur = cur->next;
4889 }
4890}
4891
4892/**
4893 * xmlDtdDumpOutput:
4894 * @buf: the XML buffer output
4895 * @doc: the document
4896 * @encoding: an optional encoding string
4897 *
4898 * Dump the XML document DTD, if any.
4899 */
4900static void
4901xmlDtdDumpOutput(xmlOutputBufferPtr buf, xmlDtdPtr dtd, const char *encoding) {
4902 if (dtd == NULL) {
4903#ifdef DEBUG_TREE
4904 fprintf(stderr, "xmlDtdDump : no internal subset\n");
4905#endif
4906 return;
4907 }
4908 xmlOutputBufferWriteString(buf, "<!DOCTYPE ");
4909 xmlOutputBufferWriteString(buf, (const char *)dtd->name);
4910 if (dtd->ExternalID != NULL) {
4911 xmlOutputBufferWriteString(buf, " PUBLIC ");
4912 xmlBufferWriteQuotedString(buf->buffer, dtd->ExternalID);
4913 xmlOutputBufferWriteString(buf, " ");
4914 xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
4915 } else if (dtd->SystemID != NULL) {
4916 xmlOutputBufferWriteString(buf, " SYSTEM ");
4917 xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
4918 }
4919 if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
4920 (dtd->attributes == NULL) && (dtd->notations == NULL)) {
4921 xmlOutputBufferWriteString(buf, ">");
4922 return;
4923 }
4924 xmlOutputBufferWriteString(buf, " [\n");
4925 xmlNodeListDumpOutput(buf, dtd->doc, dtd->children, -1, 0, encoding);
4926#if 0
4927 if (dtd->entities != NULL)
4928 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) dtd->entities);
4929 if (dtd->notations != NULL)
4930 xmlDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations);
4931 if (dtd->elements != NULL)
4932 xmlDumpElementTable(buf, (xmlElementTablePtr) dtd->elements);
4933 if (dtd->attributes != NULL)
4934 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) dtd->attributes);
4935#endif
4936 xmlOutputBufferWriteString(buf, "]>");
4937}
4938
4939/**
4940 * xmlAttrDumpOutput:
4941 * @buf: the XML buffer output
4942 * @doc: the document
4943 * @cur: the attribute pointer
4944 * @encoding: an optional encoding string
4945 *
4946 * Dump an XML attribute
4947 */
4948static void
4949xmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur,
4950 const char *encoding) {
4951 xmlChar *value;
4952
4953 if (cur == NULL) {
4954#ifdef DEBUG_TREE
4955 fprintf(stderr, "xmlAttrDump : property == NULL\n");
4956#endif
4957 return;
4958 }
4959 xmlOutputBufferWriteString(buf, " ");
4960 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
4961 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
4962 xmlOutputBufferWriteString(buf, ":");
4963 }
4964 xmlOutputBufferWriteString(buf, (const char *)cur->name);
4965 value = xmlNodeListGetString(doc, cur->children, 0);
4966 if (value) {
4967 xmlOutputBufferWriteString(buf, "=");
4968 xmlBufferWriteQuotedString(buf->buffer, value);
4969 xmlFree(value);
4970 } else {
4971 xmlOutputBufferWriteString(buf, "=\"\"");
4972 }
4973}
4974
4975/**
4976 * xmlAttrListDumpOutput:
4977 * @buf: the XML buffer output
4978 * @doc: the document
4979 * @cur: the first attribute pointer
4980 * @encoding: an optional encoding string
4981 *
4982 * Dump a list of XML attributes
4983 */
4984static void
4985xmlAttrListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
4986 xmlAttrPtr cur, const char *encoding) {
4987 if (cur == NULL) {
4988#ifdef DEBUG_TREE
4989 fprintf(stderr, "xmlAttrListDump : property == NULL\n");
4990#endif
4991 return;
4992 }
4993 while (cur != NULL) {
4994 xmlAttrDumpOutput(buf, doc, cur, encoding);
4995 cur = cur->next;
4996 }
4997}
4998
4999
5000
5001/**
5002 * xmlNodeListDumpOutput:
5003 * @buf: the XML buffer output
5004 * @doc: the document
5005 * @cur: the first node
5006 * @level: the imbrication level for indenting
5007 * @format: is formatting allowed
5008 * @encoding: an optional encoding string
5009 *
5010 * Dump an XML node list, recursive behaviour,children are printed too.
5011 */
5012static void
5013xmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
5014 xmlNodePtr cur, int level, int format, const char *encoding) {
5015 int i;
5016
5017 if (cur == NULL) {
5018#ifdef DEBUG_TREE
5019 fprintf(stderr, "xmlNodeListDump : node == NULL\n");
5020#endif
5021 return;
5022 }
5023 while (cur != NULL) {
5024 if ((format) && (xmlIndentTreeOutput) &&
5025 (cur->type == XML_ELEMENT_NODE))
5026 for (i = 0;i < level;i++)
5027 xmlOutputBufferWriteString(buf, " ");
5028 xmlNodeDumpOutput(buf, doc, cur, level, format, encoding);
5029 if (format) {
5030 xmlOutputBufferWriteString(buf, "\n");
5031 }
5032 cur = cur->next;
5033 }
5034}
5035
5036/**
5037 * xmlNodeDumpOutput:
5038 * @buf: the XML buffer output
5039 * @doc: the document
5040 * @cur: the current node
5041 * @level: the imbrication level for indenting
5042 * @format: is formatting allowed
5043 * @encoding: an optional encoding string
5044 *
5045 * Dump an XML node, recursive behaviour,children are printed too.
5046 */
Daniel Veillardb656ebe2000-09-22 13:51:48 +00005047void
Daniel Veillardbe803962000-06-28 23:40:59 +00005048xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
5049 int level, int format, const char *encoding) {
5050 int i;
5051 xmlNodePtr tmp;
5052
5053 if (cur == NULL) {
5054#ifdef DEBUG_TREE
5055 fprintf(stderr, "xmlNodeDump : node == NULL\n");
5056#endif
5057 return;
5058 }
5059 if (cur->type == XML_DTD_NODE) {
5060 xmlDtdDumpOutput(buf, (xmlDtdPtr) cur, encoding);
5061 return;
5062 }
5063 if (cur->type == XML_ELEMENT_DECL) {
5064 xmlDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
5065 return;
5066 }
5067 if (cur->type == XML_ATTRIBUTE_DECL) {
5068 xmlDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
5069 return;
5070 }
5071 if (cur->type == XML_ENTITY_DECL) {
5072 xmlDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
5073 return;
5074 }
5075 if (cur->type == XML_TEXT_NODE) {
5076 if (cur->content != NULL) {
5077 xmlChar *buffer;
5078
5079#ifndef XML_USE_BUFFER_CONTENT
5080 if (encoding == NULL)
5081 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
5082 else
5083 buffer = xmlEncodeSpecialChars(doc, cur->content);
5084#else
5085 if (encoding == NULL)
5086 buffer = xmlEncodeEntitiesReentrant(doc,
5087 xmlBufferContent(cur->content));
5088 else
5089 buffer = xmlEncodeSpecialChars(doc,
5090 xmlBufferContent(cur->content));
5091#endif
5092 if (buffer != NULL) {
5093 xmlOutputBufferWriteString(buf, (const char *)buffer);
5094 xmlFree(buffer);
5095 }
5096 }
5097 return;
5098 }
5099 if (cur->type == XML_PI_NODE) {
5100 if (cur->content != NULL) {
5101 xmlOutputBufferWriteString(buf, "<?");
5102 xmlOutputBufferWriteString(buf, (const char *)cur->name);
5103 if (cur->content != NULL) {
5104 xmlOutputBufferWriteString(buf, " ");
5105#ifndef XML_USE_BUFFER_CONTENT
5106 xmlOutputBufferWriteString(buf, (const char *)cur->content);
5107#else
5108 xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
5109#endif
5110 }
5111 xmlOutputBufferWriteString(buf, "?>");
5112 } else {
5113 xmlOutputBufferWriteString(buf, "<?");
5114 xmlOutputBufferWriteString(buf, (const char *)cur->name);
5115 xmlOutputBufferWriteString(buf, "?>");
5116 }
5117 return;
5118 }
5119 if (cur->type == XML_COMMENT_NODE) {
5120 if (cur->content != NULL) {
5121 xmlOutputBufferWriteString(buf, "<!--");
5122#ifndef XML_USE_BUFFER_CONTENT
5123 xmlOutputBufferWriteString(buf, (const char *)cur->content);
5124#else
5125 xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
5126#endif
5127 xmlOutputBufferWriteString(buf, "-->");
5128 }
5129 return;
5130 }
5131 if (cur->type == XML_ENTITY_REF_NODE) {
5132 xmlOutputBufferWriteString(buf, "&");
5133 xmlOutputBufferWriteString(buf, (const char *)cur->name);
5134 xmlOutputBufferWriteString(buf, ";");
5135 return;
5136 }
5137 if (cur->type == XML_CDATA_SECTION_NODE) {
5138 xmlOutputBufferWriteString(buf, "<![CDATA[");
5139 if (cur->content != NULL)
5140#ifndef XML_USE_BUFFER_CONTENT
5141 xmlOutputBufferWriteString(buf, (const char *)cur->content);
5142#else
5143 xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
5144#endif
5145 xmlOutputBufferWriteString(buf, "]]>");
5146 return;
5147 }
5148
5149 if (format == 1) {
5150 tmp = cur->children;
5151 while (tmp != NULL) {
5152 if ((tmp->type == XML_TEXT_NODE) ||
5153 (tmp->type == XML_ENTITY_REF_NODE)) {
5154 format = 0;
5155 break;
5156 }
5157 tmp = tmp->next;
5158 }
5159 }
5160 xmlOutputBufferWriteString(buf, "<");
5161 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5162 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
5163 xmlOutputBufferWriteString(buf, ":");
5164 }
5165
5166 xmlOutputBufferWriteString(buf, (const char *)cur->name);
5167 if (cur->nsDef)
5168 xmlNsListDumpOutput(buf, cur->nsDef);
5169 if (cur->properties != NULL)
5170 xmlAttrListDumpOutput(buf, doc, cur->properties, encoding);
5171
5172 if ((cur->content == NULL) && (cur->children == NULL) &&
5173 (!xmlSaveNoEmptyTags)) {
5174 xmlOutputBufferWriteString(buf, "/>");
5175 return;
5176 }
5177 xmlOutputBufferWriteString(buf, ">");
5178 if (cur->content != NULL) {
5179 xmlChar *buffer;
5180
5181#ifndef XML_USE_BUFFER_CONTENT
5182 if (encoding == NULL)
5183 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
5184 else
5185 buffer = xmlEncodeSpecialChars(doc, cur->content);
5186#else
5187 if (encoding == NULL)
5188 buffer = xmlEncodeEntitiesReentrant(doc,
5189 xmlBufferContent(cur->content));
5190 else
5191 buffer = xmlEncodeSpecialChars(doc,
5192 xmlBufferContent(cur->content));
5193#endif
5194 if (buffer != NULL) {
5195 xmlOutputBufferWriteString(buf, (const char *)buffer);
5196 xmlFree(buffer);
5197 }
5198 }
5199 if (cur->children != NULL) {
5200 if (format) xmlOutputBufferWriteString(buf, "\n");
5201 xmlNodeListDumpOutput(buf, doc, cur->children,
5202 (level >= 0?level+1:-1), format, encoding);
5203 if ((xmlIndentTreeOutput) && (format))
5204 for (i = 0;i < level;i++)
5205 xmlOutputBufferWriteString(buf, " ");
5206 }
5207 xmlOutputBufferWriteString(buf, "</");
5208 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5209 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
5210 xmlOutputBufferWriteString(buf, ":");
5211 }
5212
5213 xmlOutputBufferWriteString(buf, (const char *)cur->name);
5214 xmlOutputBufferWriteString(buf, ">");
5215}
5216
5217/**
5218 * xmlDocContentDumpOutput:
5219 * @buf: the XML buffer output
5220 * @cur: the document
5221 * @encoding: an optional encoding string
5222 *
5223 * Dump an XML document.
5224 */
5225static void
5226xmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
5227 const char *encoding) {
5228 xmlOutputBufferWriteString(buf, "<?xml version=");
5229 if (cur->version != NULL)
5230 xmlBufferWriteQuotedString(buf->buffer, cur->version);
5231 else
5232 xmlOutputBufferWriteString(buf, "\"1.0\"");
5233 if (encoding == NULL) {
5234 if (cur->encoding != NULL)
5235 encoding = (const char *) cur->encoding;
5236 else if (cur->charset != XML_CHAR_ENCODING_UTF8)
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005237 encoding = xmlGetCharEncodingName((xmlCharEncoding) cur->charset);
Daniel Veillardbe803962000-06-28 23:40:59 +00005238 }
5239 if (encoding != NULL) {
5240 xmlOutputBufferWriteString(buf, " encoding=");
5241 xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
5242 }
5243 switch (cur->standalone) {
5244 case 0:
5245 xmlOutputBufferWriteString(buf, " standalone=\"no\"");
5246 break;
5247 case 1:
5248 xmlOutputBufferWriteString(buf, " standalone=\"yes\"");
5249 break;
5250 }
5251 xmlOutputBufferWriteString(buf, "?>\n");
5252 if (cur->children != NULL) {
5253 xmlNodePtr child = cur->children;
5254
5255 /* global namespace definitions, the old way */
5256 if (oldXMLWDcompatibility)
5257 xmlGlobalNsListDumpOutput(buf, cur->oldNs);
5258 else
5259 xmlUpgradeOldNs(cur);
5260
5261 while (child != NULL) {
5262 xmlNodeDumpOutput(buf, cur, child, 0, 1, encoding);
5263 xmlOutputBufferWriteString(buf, "\n");
5264 child = child->next;
5265 }
5266 }
5267}
5268
5269/************************************************************************
5270 * *
5271 * Saving functions front-ends *
5272 * *
5273 ************************************************************************/
5274
Daniel Veillard97b58771998-10-20 06:14:16 +00005275/**
5276 * xmlDocDumpMemory:
5277 * @cur: the document
5278 * @mem: OUT: the memory pointer
5279 * @size: OUT: the memory lenght
5280 *
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005281 * Dump an XML document in memory and return the xmlChar * and it's size.
Daniel Veillard97b58771998-10-20 06:14:16 +00005282 * It's up to the caller to free the memory.
Daniel Veillard260a68f1998-08-13 03:39:55 +00005283 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00005284void
Daniel Veillarddd6b3671999-09-23 22:19:22 +00005285xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
Daniel Veillard5099ae81999-04-21 20:12:07 +00005286 xmlBufferPtr buf;
5287
Daniel Veillard260a68f1998-08-13 03:39:55 +00005288 if (cur == NULL) {
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00005289#ifdef DEBUG_TREE
5290 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
5291#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +00005292 *mem = NULL;
5293 *size = 0;
5294 return;
5295 }
Daniel Veillard5099ae81999-04-21 20:12:07 +00005296 buf = xmlBufferCreate();
5297 if (buf == NULL) {
5298 *mem = NULL;
5299 *size = 0;
5300 return;
5301 }
5302 xmlDocContentDump(buf, cur);
Daniel Veillardb05deb71999-08-10 19:04:08 +00005303 *mem = xmlStrndup(buf->content, buf->use);
Daniel Veillard5099ae81999-04-21 20:12:07 +00005304 *size = buf->use;
Daniel Veillardb05deb71999-08-10 19:04:08 +00005305 xmlBufferFree(buf);
Daniel Veillard260a68f1998-08-13 03:39:55 +00005306}
5307
Daniel Veillard97b58771998-10-20 06:14:16 +00005308/**
5309 * xmlGetDocCompressMode:
5310 * @doc: the document
5311 *
5312 * get the compression ratio for a document, ZLIB based
Daniel Veillard1e346af1999-02-22 10:33:01 +00005313 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard151b1b01998-09-23 00:49:46 +00005314 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00005315int
Daniel Veillarddbfd6411999-12-28 16:35:14 +00005316xmlGetDocCompressMode (xmlDocPtr doc) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00005317 if (doc == NULL) return(-1);
5318 return(doc->compression);
5319}
5320
Daniel Veillard97b58771998-10-20 06:14:16 +00005321/**
5322 * xmlSetDocCompressMode:
5323 * @doc: the document
5324 * @mode: the compression ratio
5325 *
5326 * set the compression ratio for a document, ZLIB based
5327 * Correct values: 0 (uncompressed) to 9 (max compression)
5328 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00005329void
5330xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
Daniel Veillard15a8df41998-09-24 19:15:06 +00005331 if (doc == NULL) return;
5332 if (mode < 0) doc->compression = 0;
5333 else if (mode > 9) doc->compression = 9;
5334 else doc->compression = mode;
5335}
5336
Daniel Veillard97b58771998-10-20 06:14:16 +00005337/**
5338 * xmlGetCompressMode:
5339 *
5340 * get the default compression mode used, ZLIB based.
Daniel Veillard1e346af1999-02-22 10:33:01 +00005341 * Returns 0 (uncompressed) to 9 (max compression)
Daniel Veillard15a8df41998-09-24 19:15:06 +00005342 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00005343int
5344 xmlGetCompressMode(void) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00005345 return(xmlCompressMode);
5346}
Daniel Veillard97b58771998-10-20 06:14:16 +00005347
5348/**
5349 * xmlSetCompressMode:
5350 * @mode: the compression ratio
5351 *
5352 * set the default compression mode used, ZLIB based
5353 * Correct values: 0 (uncompressed) to 9 (max compression)
5354 */
Daniel Veillardbaf4cd51998-10-27 22:56:57 +00005355void
5356xmlSetCompressMode(int mode) {
Daniel Veillard151b1b01998-09-23 00:49:46 +00005357 if (mode < 0) xmlCompressMode = 0;
Daniel Veillard15a8df41998-09-24 19:15:06 +00005358 else if (mode > 9) xmlCompressMode = 9;
Daniel Veillard151b1b01998-09-23 00:49:46 +00005359 else xmlCompressMode = mode;
5360}
5361
Daniel Veillardbe803962000-06-28 23:40:59 +00005362/**
5363 * xmlDocDump:
5364 * @f: the FILE*
5365 * @cur: the document
5366 *
5367 * Dump an XML document to an open FILE.
5368 *
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005369 * returns: the number of byte written or -1 in case of failure.
Daniel Veillardbe803962000-06-28 23:40:59 +00005370 */
5371int
5372xmlDocDump(FILE *f, xmlDocPtr cur) {
5373 xmlOutputBufferPtr buf;
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005374 const char * encoding;
5375 xmlCharEncodingHandlerPtr handler = NULL;
Daniel Veillardbe803962000-06-28 23:40:59 +00005376 int ret;
Daniel Veillard151b1b01998-09-23 00:49:46 +00005377
Daniel Veillardbe803962000-06-28 23:40:59 +00005378 if (cur == NULL) {
5379#ifdef DEBUG_TREE
5380 fprintf(stderr, "xmlDocDump : document == NULL\n");
5381#endif
5382 return(-1);
5383 }
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005384 encoding = (const char *) cur->encoding;
5385
5386 if (encoding != NULL) {
5387 xmlCharEncoding enc;
5388
5389 enc = xmlParseCharEncoding(encoding);
5390
5391 if (cur->charset != XML_CHAR_ENCODING_UTF8) {
5392 fprintf(stderr, "xmlDocDump: document not in UTF8\n");
5393 return(-1);
5394 }
5395 if (enc != XML_CHAR_ENCODING_UTF8) {
5396 handler = xmlFindCharEncodingHandler(encoding);
5397 if (handler == NULL) {
5398 xmlFree((char *) cur->encoding);
5399 cur->encoding = NULL;
5400 }
5401 }
5402 }
5403 buf = xmlOutputBufferCreateFile(f, handler);
Daniel Veillardbe803962000-06-28 23:40:59 +00005404 if (buf == NULL) return(-1);
5405 xmlDocContentDumpOutput(buf, cur, NULL);
5406
5407 ret = xmlOutputBufferClose(buf);
5408 return(ret);
5409}
5410
5411/**
Daniel Veillardbe803962000-06-28 23:40:59 +00005412 * xmlSaveFileTo:
5413 * @buf: an output I/O buffer
5414 * @cur: the document
5415 * @encoding: the encoding if any assuming the i/O layer handles the trancoding
5416 *
5417 * Dump an XML document to an I/O buffer.
5418 *
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005419 * returns: the number of byte written or -1 in case of failure.
Daniel Veillardbe803962000-06-28 23:40:59 +00005420 */
5421int
5422xmlSaveFileTo(xmlOutputBuffer *buf, xmlDocPtr cur, const char *encoding) {
5423 int ret;
5424
5425 if (buf == NULL) return(0);
5426 xmlDocContentDumpOutput(buf, cur, encoding);
5427 ret = xmlOutputBufferClose(buf);
5428 return(ret);
5429}
5430
5431/**
5432 * xmlSaveFileEnc:
5433 * @filename: the filename (or URL)
5434 * @cur: the document
5435 * @encoding: the name of an encoding (or NULL)
5436 *
5437 * Dump an XML document, converting it to the given encoding
5438 *
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005439 * returns: the number of byte written or -1 in case of failure.
Daniel Veillardbe803962000-06-28 23:40:59 +00005440 */
5441int
5442xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) {
5443 xmlOutputBufferPtr buf;
5444 xmlCharEncodingHandlerPtr handler = NULL;
5445 int ret;
5446
5447 if (encoding != NULL) {
5448 xmlCharEncoding enc;
5449
5450 enc = xmlParseCharEncoding(encoding);
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005451 if (cur->charset != XML_CHAR_ENCODING_UTF8) {
5452 fprintf(stderr, "xmlSaveFileEnc: document not in UTF8\n");
5453 return(-1);
5454 }
5455 if (enc != XML_CHAR_ENCODING_UTF8) {
5456 handler = xmlFindCharEncodingHandler(encoding);
5457 if (handler == NULL) {
Daniel Veillardbe803962000-06-28 23:40:59 +00005458 return(-1);
5459 }
Daniel Veillardbe803962000-06-28 23:40:59 +00005460 }
5461 }
5462
5463 /*
5464 * save the content to a temp buffer.
5465 */
5466 buf = xmlOutputBufferCreateFilename(filename, handler, 0);
5467 if (buf == NULL) return(0);
5468
5469 xmlDocContentDumpOutput(buf, cur, encoding);
5470
5471 ret = xmlOutputBufferClose(buf);
5472 return(ret);
5473}
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005474
5475/**
5476 * xmlSaveFile:
5477 * @filename: the filename (or URL)
5478 * @cur: the document
5479 *
5480 * Dump an XML document to a file. Will use compression if
5481 * compiled in and enabled. If @filename is "-" the stdout file is
5482 * used.
5483 * returns: the number of byte written or -1 in case of failure.
5484 */
5485int
5486xmlSaveFile(const char *filename, xmlDocPtr cur) {
5487 xmlOutputBufferPtr buf;
5488 const char *encoding;
5489 xmlCharEncodingHandlerPtr handler = NULL;
5490 int ret;
5491
5492 if (cur == NULL)
5493 return(-1);
5494 encoding = (const char *) cur->encoding;
5495
5496 /*
5497 * save the content to a temp buffer.
5498 */
5499#ifdef HAVE_ZLIB_H
5500 if (cur->compression < 0) cur->compression = xmlCompressMode;
Daniel Veillardbe803962000-06-28 23:40:59 +00005501#endif
Daniel Veillard32bc74e2000-07-14 14:49:25 +00005502 if (encoding != NULL) {
5503 xmlCharEncoding enc;
5504
5505 enc = xmlParseCharEncoding(encoding);
5506
5507 if (cur->charset != XML_CHAR_ENCODING_UTF8) {
5508 fprintf(stderr, "xmlSaveFile: document not in UTF8\n");
5509 return(-1);
5510 }
5511 if (enc != XML_CHAR_ENCODING_UTF8) {
5512 handler = xmlFindCharEncodingHandler(encoding);
5513 if (handler == NULL) {
5514 xmlFree((char *) cur->encoding);
5515 cur->encoding = NULL;
5516 }
5517 }
5518 }
5519
5520 buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
5521 if (buf == NULL) return(0);
5522
5523 xmlDocContentDumpOutput(buf, cur, NULL);
5524
5525 ret = xmlOutputBufferClose(buf);
5526 return(ret);
5527}
5528