Bug Summary

File:tree.c
Location:line 1424, column 3
Description:Value stored to 'last' is never read

Annotated Source Code

1/*
2 * tree.c : implementation of access function for an XML tree.
3 *
4 * References:
5 * XHTML 1.0 W3C REC: http://www.w3.org/TR/2002/REC-xhtml1-20020801/
6 *
7 * See Copyright for the status of this software.
8 *
9 * daniel@veillard.com
10 *
11 */
12
13#define IN_LIBXML
14#include "libxml.h"
15
16#include <string.h> /* for memset() only ! */
17#include <limits.h>
18#ifdef HAVE_CTYPE_H1
19#include <ctype.h>
20#endif
21#ifdef HAVE_STDLIB_H1
22#include <stdlib.h>
23#endif
24#ifdef HAVE_ZLIB_H1
25#include <zlib.h>
26#endif
27
28#include <libxml/xmlmemory.h>
29#include <libxml/tree.h>
30#include <libxml/parser.h>
31#include <libxml/uri.h>
32#include <libxml/entities.h>
33#include <libxml/valid.h>
34#include <libxml/xmlerror.h>
35#include <libxml/parserInternals.h>
36#include <libxml/globals.h>
37#ifdef LIBXML_HTML_ENABLED
38#include <libxml/HTMLtree.h>
39#endif
40#ifdef LIBXML_DEBUG_ENABLED
41#include <libxml/debugXML.h>
42#endif
43
44int __xmlRegisterCallbacks = 0;
45
46/************************************************************************
47 * *
48 * Forward declarations *
49 * *
50 ************************************************************************/
51
52static xmlNsPtr
53xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns);
54
55static xmlChar* xmlGetPropNodeValueInternal(xmlAttrPtr prop);
56
57/************************************************************************
58 * *
59 * Tree memory error handler *
60 * *
61 ************************************************************************/
62/**
63 * xmlTreeErrMemory:
64 * @extra: extra informations
65 *
66 * Handle an out of memory condition
67 */
68static void
69xmlTreeErrMemory(const char *extra)
70{
71 __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL((void*)0), NULL((void*)0), extra);
72}
73
74/**
75 * xmlTreeErr:
76 * @code: the error number
77 * @extra: extra informations
78 *
79 * Handle an out of memory condition
80 */
81static void
82xmlTreeErr(int code, xmlNodePtr node, const char *extra)
83{
84 const char *msg = NULL((void*)0);
85
86 switch(code) {
87 case XML_TREE_INVALID_HEX:
88 msg = "invalid hexadecimal character value\n";
89 break;
90 case XML_TREE_INVALID_DEC:
91 msg = "invalid decimal character value\n";
92 break;
93 case XML_TREE_UNTERMINATED_ENTITY:
94 msg = "unterminated entity reference %15s\n";
95 break;
96 case XML_TREE_NOT_UTF8:
97 msg = "string is not in UTF-8\n";
98 break;
99 default:
100 msg = "unexpected error number\n";
101 }
102 __xmlSimpleError(XML_FROM_TREE, code, node, msg, extra);
103}
104
105/************************************************************************
106 * *
107 * A few static variables and macros *
108 * *
109 ************************************************************************/
110/* #undef xmlStringText */
111const xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
112/* #undef xmlStringTextNoenc */
113const xmlChar xmlStringTextNoenc[] =
114 { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 };
115/* #undef xmlStringComment */
116const xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
117
118static int xmlCompressMode = 0;
119static int xmlCheckDTD = 1;
120
121#define UPDATE_LAST_CHILD_AND_PARENT(n)if ((n) != ((void*)0)) { xmlNodePtr ulccur = (n)->children
; if (ulccur == ((void*)0)) { (n)->last = ((void*)0); } else
{ while (ulccur->next != ((void*)0)) { ulccur->parent =
(n); ulccur = ulccur->next; } ulccur->parent = (n); (n
)->last = ulccur; }}
if ((n) != NULL((void*)0)) { \
122 xmlNodePtr ulccur = (n)->children; \
123 if (ulccur == NULL((void*)0)) { \
124 (n)->last = NULL((void*)0); \
125 } else { \
126 while (ulccur->next != NULL((void*)0)) { \
127 ulccur->parent = (n); \
128 ulccur = ulccur->next; \
129 } \
130 ulccur->parent = (n); \
131 (n)->last = ulccur; \
132}}
133
134#define IS_STR_XML(str)((str != ((void*)0)) && (str[0] == 'x') && (str
[1] == 'm') && (str[2] == 'l') && (str[3] == 0
))
((str != NULL((void*)0)) && (str[0] == 'x') && \
135 (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
136
137/* #define DEBUG_BUFFER */
138/* #define DEBUG_TREE */
139
140/************************************************************************
141 * *
142 * Functions to move to entities.c once the *
143 * API freeze is smoothen and they can be made public. *
144 * *
145 ************************************************************************/
146#include <libxml/hash.h>
147
148#ifdef LIBXML_TREE_ENABLED
149/**
150 * xmlGetEntityFromDtd:
151 * @dtd: A pointer to the DTD to search
152 * @name: The entity name
153 *
154 * Do an entity lookup in the DTD entity hash table and
155 * return the corresponding entity, if found.
156 *
157 * Returns A pointer to the entity structure or NULL if not found.
158 */
159static xmlEntityPtr
160xmlGetEntityFromDtd(xmlDtdPtr dtd, const xmlChar *name) {
161 xmlEntitiesTablePtr table;
162
163 if((dtd != NULL((void*)0)) && (dtd->entities != NULL((void*)0))) {
164 table = (xmlEntitiesTablePtr) dtd->entities;
165 return((xmlEntityPtr) xmlHashLookup(table, name));
166 /* return(xmlGetEntityFromTable(table, name)); */
167 }
168 return(NULL((void*)0));
169}
170/**
171 * xmlGetParameterEntityFromDtd:
172 * @dtd: A pointer to the DTD to search
173 * @name: The entity name
174 *
175 * Do an entity lookup in the DTD pararmeter entity hash table and
176 * return the corresponding entity, if found.
177 *
178 * Returns A pointer to the entity structure or NULL if not found.
179 */
180static xmlEntityPtr
181xmlGetParameterEntityFromDtd(xmlDtdPtr dtd, const xmlChar *name) {
182 xmlEntitiesTablePtr table;
183
184 if ((dtd != NULL((void*)0)) && (dtd->pentities != NULL((void*)0))) {
185 table = (xmlEntitiesTablePtr) dtd->pentities;
186 return((xmlEntityPtr) xmlHashLookup(table, name));
187 /* return(xmlGetEntityFromTable(table, name)); */
188 }
189 return(NULL((void*)0));
190}
191#endif /* LIBXML_TREE_ENABLED */
192
193/************************************************************************
194 * *
195 * QName handling helper *
196 * *
197 ************************************************************************/
198
199/**
200 * xmlBuildQName:
201 * @ncname: the Name
202 * @prefix: the prefix
203 * @memory: preallocated memory
204 * @len: preallocated memory length
205 *
206 * Builds the QName @prefix:@ncname in @memory if there is enough space
207 * and prefix is not NULL nor empty, otherwise allocate a new string.
208 * If prefix is NULL or empty it returns ncname.
209 *
210 * Returns the new string which must be freed by the caller if different from
211 * @memory and @ncname or NULL in case of error
212 */
213xmlChar *
214xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix,
215 xmlChar *memory, int len) {
216 int lenn, lenp;
217 xmlChar *ret;
218
219 if (ncname == NULL((void*)0)) return(NULL((void*)0));
220 if (prefix == NULL((void*)0)) return((xmlChar *) ncname);
221
222 lenn = strlen((char *) ncname);
223 lenp = strlen((char *) prefix);
224
225 if ((memory == NULL((void*)0)) || (len < lenn + lenp + 2)) {
226 ret = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
227 if (ret == NULL((void*)0)) {
228 xmlTreeErrMemory("building QName");
229 return(NULL((void*)0));
230 }
231 } else {
232 ret = memory;
233 }
234 memcpy(&ret[0], prefix, lenp);
235 ret[lenp] = ':';
236 memcpy(&ret[lenp + 1], ncname, lenn);
237 ret[lenn + lenp + 1] = 0;
238 return(ret);
239}
240
241/**
242 * xmlSplitQName2:
243 * @name: the full QName
244 * @prefix: a xmlChar **
245 *
246 * parse an XML qualified name string
247 *
248 * [NS 5] QName ::= (Prefix ':')? LocalPart
249 *
250 * [NS 6] Prefix ::= NCName
251 *
252 * [NS 7] LocalPart ::= NCName
253 *
254 * Returns NULL if not a QName, otherwise the local part, and prefix
255 * is updated to get the Prefix if any.
256 */
257
258xmlChar *
259xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
260 int len = 0;
261 xmlChar *ret = NULL((void*)0);
262
263 if (prefix == NULL((void*)0)) return(NULL((void*)0));
264 *prefix = NULL((void*)0);
265 if (name == NULL((void*)0)) return(NULL((void*)0));
266
267#ifndef XML_XML_NAMESPACE(const xmlChar *) "http://www.w3.org/XML/1998/namespace"
268 /* xml: prefix is not really a namespace */
269 if ((name[0] == 'x') && (name[1] == 'm') &&
270 (name[2] == 'l') && (name[3] == ':'))
271 return(NULL((void*)0));
272#endif
273
274 /* nasty but valid */
275 if (name[0] == ':')
276 return(NULL((void*)0));
277
278 /*
279 * we are not trying to validate but just to cut, and yes it will
280 * work even if this is as set of UTF-8 encoded chars
281 */
282 while ((name[len] != 0) && (name[len] != ':'))
283 len++;
284
285 if (name[len] == 0)
286 return(NULL((void*)0));
287
288 *prefix = xmlStrndup(name, len);
289 if (*prefix == NULL((void*)0)) {
290 xmlTreeErrMemory("QName split");
291 return(NULL((void*)0));
292 }
293 ret = xmlStrdup(&name[len + 1]);
294 if (ret == NULL((void*)0)) {
295 xmlTreeErrMemory("QName split");
296 if (*prefix != NULL((void*)0)) {
297 xmlFree(*prefix);
298 *prefix = NULL((void*)0);
299 }
300 return(NULL((void*)0));
301 }
302
303 return(ret);
304}
305
306/**
307 * xmlSplitQName3:
308 * @name: the full QName
309 * @len: an int *
310 *
311 * parse an XML qualified name string,i
312 *
313 * returns NULL if it is not a Qualified Name, otherwise, update len
314 * with the lenght in byte of the prefix and return a pointer
315 * to the start of the name without the prefix
316 */
317
318const xmlChar *
319xmlSplitQName3(const xmlChar *name, int *len) {
320 int l = 0;
321
322 if (name == NULL((void*)0)) return(NULL((void*)0));
323 if (len == NULL((void*)0)) return(NULL((void*)0));
324
325 /* nasty but valid */
326 if (name[0] == ':')
327 return(NULL((void*)0));
328
329 /*
330 * we are not trying to validate but just to cut, and yes it will
331 * work even if this is as set of UTF-8 encoded chars
332 */
333 while ((name[l] != 0) && (name[l] != ':'))
334 l++;
335
336 if (name[l] == 0)
337 return(NULL((void*)0));
338
339 *len = l;
340
341 return(&name[l+1]);
342}
343
344/************************************************************************
345 * *
346 * Check Name, NCName and QName strings *
347 * *
348 ************************************************************************/
349
350#define CUR_SCHAR(s, l)xmlStringCurrentChar(((void*)0), s, &l) xmlStringCurrentChar(NULL((void*)0), s, &l)
351
352#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED)
353/**
354 * xmlValidateNCName:
355 * @value: the value to check
356 * @space: allow spaces in front and end of the string
357 *
358 * Check that a value conforms to the lexical space of NCName
359 *
360 * Returns 0 if this validates, a positive error code number otherwise
361 * and -1 in case of internal or API error.
362 */
363int
364xmlValidateNCName(const xmlChar *value, int space) {
365 const xmlChar *cur = value;
366 int c,l;
367
368 if (value == NULL((void*)0))
369 return(-1);
370
371 /*
372 * First quick algorithm for ASCII range
373 */
374 if (space)
375 while (IS_BLANK_CH(*cur)(((*cur) == 0x20) || ((0x9 <= (*cur)) && ((*cur) <=
0xa)) || ((*cur) == 0xd))
) cur++;
376 if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
377 (*cur == '_'))
378 cur++;
379 else
380 goto try_complex;
381 while (((*cur >= 'a') && (*cur <= 'z')) ||
382 ((*cur >= 'A') && (*cur <= 'Z')) ||
383 ((*cur >= '0') && (*cur <= '9')) ||
384 (*cur == '_') || (*cur == '-') || (*cur == '.'))
385 cur++;
386 if (space)
387 while (IS_BLANK_CH(*cur)(((*cur) == 0x20) || ((0x9 <= (*cur)) && ((*cur) <=
0xa)) || ((*cur) == 0xd))
) cur++;
388 if (*cur == 0)
389 return(0);
390
391try_complex:
392 /*
393 * Second check for chars outside the ASCII range
394 */
395 cur = value;
396 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
397 if (space) {
398 while (IS_BLANK(c)(((c) < 0x100) ? ((((c)) == 0x20) || ((0x9 <= ((c))) &&
(((c)) <= 0xa)) || (((c)) == 0xd)) : 0)
) {
399 cur += l;
400 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
401 }
402 }
403 if ((!IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
) && (c != '_'))
404 return(1);
405 cur += l;
406 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
407 while (IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
|| IS_DIGIT(c)(((c) < 0x100) ? (((0x30 <= ((c))) && (((c)) <=
0x39))) : xmlCharInRange((c), &xmlIsDigitGroup))
|| (c == '.') ||
408 (c == '-') || (c == '_') || IS_COMBINING(c)(((c) < 0x100) ? 0 : xmlCharInRange((c), &xmlIsCombiningGroup
))
||
409 IS_EXTENDER(c)(((c) < 0x100) ? ((((c)) == 0xb7)) : xmlCharInRange((c), &
xmlIsExtenderGroup))
) {
410 cur += l;
411 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
412 }
413 if (space) {
414 while (IS_BLANK(c)(((c) < 0x100) ? ((((c)) == 0x20) || ((0x9 <= ((c))) &&
(((c)) <= 0xa)) || (((c)) == 0xd)) : 0)
) {
415 cur += l;
416 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
417 }
418 }
419 if (c != 0)
420 return(1);
421
422 return(0);
423}
424#endif
425
426#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
427/**
428 * xmlValidateQName:
429 * @value: the value to check
430 * @space: allow spaces in front and end of the string
431 *
432 * Check that a value conforms to the lexical space of QName
433 *
434 * Returns 0 if this validates, a positive error code number otherwise
435 * and -1 in case of internal or API error.
436 */
437int
438xmlValidateQName(const xmlChar *value, int space) {
439 const xmlChar *cur = value;
440 int c,l;
441
442 if (value == NULL((void*)0))
443 return(-1);
444 /*
445 * First quick algorithm for ASCII range
446 */
447 if (space)
448 while (IS_BLANK_CH(*cur)(((*cur) == 0x20) || ((0x9 <= (*cur)) && ((*cur) <=
0xa)) || ((*cur) == 0xd))
) cur++;
449 if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
450 (*cur == '_'))
451 cur++;
452 else
453 goto try_complex;
454 while (((*cur >= 'a') && (*cur <= 'z')) ||
455 ((*cur >= 'A') && (*cur <= 'Z')) ||
456 ((*cur >= '0') && (*cur <= '9')) ||
457 (*cur == '_') || (*cur == '-') || (*cur == '.'))
458 cur++;
459 if (*cur == ':') {
460 cur++;
461 if (((*cur >= 'a') && (*cur <= 'z')) ||
462 ((*cur >= 'A') && (*cur <= 'Z')) ||
463 (*cur == '_'))
464 cur++;
465 else
466 goto try_complex;
467 while (((*cur >= 'a') && (*cur <= 'z')) ||
468 ((*cur >= 'A') && (*cur <= 'Z')) ||
469 ((*cur >= '0') && (*cur <= '9')) ||
470 (*cur == '_') || (*cur == '-') || (*cur == '.'))
471 cur++;
472 }
473 if (space)
474 while (IS_BLANK_CH(*cur)(((*cur) == 0x20) || ((0x9 <= (*cur)) && ((*cur) <=
0xa)) || ((*cur) == 0xd))
) cur++;
475 if (*cur == 0)
476 return(0);
477
478try_complex:
479 /*
480 * Second check for chars outside the ASCII range
481 */
482 cur = value;
483 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
484 if (space) {
485 while (IS_BLANK(c)(((c) < 0x100) ? ((((c)) == 0x20) || ((0x9 <= ((c))) &&
(((c)) <= 0xa)) || (((c)) == 0xd)) : 0)
) {
486 cur += l;
487 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
488 }
489 }
490 if ((!IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
) && (c != '_'))
491 return(1);
492 cur += l;
493 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
494 while (IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
|| IS_DIGIT(c)(((c) < 0x100) ? (((0x30 <= ((c))) && (((c)) <=
0x39))) : xmlCharInRange((c), &xmlIsDigitGroup))
|| (c == '.') ||
495 (c == '-') || (c == '_') || IS_COMBINING(c)(((c) < 0x100) ? 0 : xmlCharInRange((c), &xmlIsCombiningGroup
))
||
496 IS_EXTENDER(c)(((c) < 0x100) ? ((((c)) == 0xb7)) : xmlCharInRange((c), &
xmlIsExtenderGroup))
) {
497 cur += l;
498 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
499 }
500 if (c == ':') {
501 cur += l;
502 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
503 if ((!IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
) && (c != '_'))
504 return(1);
505 cur += l;
506 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
507 while (IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
|| IS_DIGIT(c)(((c) < 0x100) ? (((0x30 <= ((c))) && (((c)) <=
0x39))) : xmlCharInRange((c), &xmlIsDigitGroup))
|| (c == '.') ||
508 (c == '-') || (c == '_') || IS_COMBINING(c)(((c) < 0x100) ? 0 : xmlCharInRange((c), &xmlIsCombiningGroup
))
||
509 IS_EXTENDER(c)(((c) < 0x100) ? ((((c)) == 0xb7)) : xmlCharInRange((c), &
xmlIsExtenderGroup))
) {
510 cur += l;
511 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
512 }
513 }
514 if (space) {
515 while (IS_BLANK(c)(((c) < 0x100) ? ((((c)) == 0x20) || ((0x9 <= ((c))) &&
(((c)) <= 0xa)) || (((c)) == 0xd)) : 0)
) {
516 cur += l;
517 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
518 }
519 }
520 if (c != 0)
521 return(1);
522 return(0);
523}
524
525/**
526 * xmlValidateName:
527 * @value: the value to check
528 * @space: allow spaces in front and end of the string
529 *
530 * Check that a value conforms to the lexical space of Name
531 *
532 * Returns 0 if this validates, a positive error code number otherwise
533 * and -1 in case of internal or API error.
534 */
535int
536xmlValidateName(const xmlChar *value, int space) {
537 const xmlChar *cur = value;
538 int c,l;
539
540 if (value == NULL((void*)0))
541 return(-1);
542 /*
543 * First quick algorithm for ASCII range
544 */
545 if (space)
546 while (IS_BLANK_CH(*cur)(((*cur) == 0x20) || ((0x9 <= (*cur)) && ((*cur) <=
0xa)) || ((*cur) == 0xd))
) cur++;
547 if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
548 (*cur == '_') || (*cur == ':'))
549 cur++;
550 else
551 goto try_complex;
552 while (((*cur >= 'a') && (*cur <= 'z')) ||
553 ((*cur >= 'A') && (*cur <= 'Z')) ||
554 ((*cur >= '0') && (*cur <= '9')) ||
555 (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
556 cur++;
557 if (space)
558 while (IS_BLANK_CH(*cur)(((*cur) == 0x20) || ((0x9 <= (*cur)) && ((*cur) <=
0xa)) || ((*cur) == 0xd))
) cur++;
559 if (*cur == 0)
560 return(0);
561
562try_complex:
563 /*
564 * Second check for chars outside the ASCII range
565 */
566 cur = value;
567 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
568 if (space) {
569 while (IS_BLANK(c)(((c) < 0x100) ? ((((c)) == 0x20) || ((0x9 <= ((c))) &&
(((c)) <= 0xa)) || (((c)) == 0xd)) : 0)
) {
570 cur += l;
571 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
572 }
573 }
574 if ((!IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
) && (c != '_') && (c != ':'))
575 return(1);
576 cur += l;
577 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
578 while (IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
|| IS_DIGIT(c)(((c) < 0x100) ? (((0x30 <= ((c))) && (((c)) <=
0x39))) : xmlCharInRange((c), &xmlIsDigitGroup))
|| (c == '.') || (c == ':') ||
579 (c == '-') || (c == '_') || IS_COMBINING(c)(((c) < 0x100) ? 0 : xmlCharInRange((c), &xmlIsCombiningGroup
))
|| IS_EXTENDER(c)(((c) < 0x100) ? ((((c)) == 0xb7)) : xmlCharInRange((c), &
xmlIsExtenderGroup))
) {
580 cur += l;
581 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
582 }
583 if (space) {
584 while (IS_BLANK(c)(((c) < 0x100) ? ((((c)) == 0x20) || ((0x9 <= ((c))) &&
(((c)) <= 0xa)) || (((c)) == 0xd)) : 0)
) {
585 cur += l;
586 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
587 }
588 }
589 if (c != 0)
590 return(1);
591 return(0);
592}
593
594/**
595 * xmlValidateNMToken:
596 * @value: the value to check
597 * @space: allow spaces in front and end of the string
598 *
599 * Check that a value conforms to the lexical space of NMToken
600 *
601 * Returns 0 if this validates, a positive error code number otherwise
602 * and -1 in case of internal or API error.
603 */
604int
605xmlValidateNMToken(const xmlChar *value, int space) {
606 const xmlChar *cur = value;
607 int c,l;
608
609 if (value == NULL((void*)0))
610 return(-1);
611 /*
612 * First quick algorithm for ASCII range
613 */
614 if (space)
615 while (IS_BLANK_CH(*cur)(((*cur) == 0x20) || ((0x9 <= (*cur)) && ((*cur) <=
0xa)) || ((*cur) == 0xd))
) cur++;
616 if (((*cur >= 'a') && (*cur <= 'z')) ||
617 ((*cur >= 'A') && (*cur <= 'Z')) ||
618 ((*cur >= '0') && (*cur <= '9')) ||
619 (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
620 cur++;
621 else
622 goto try_complex;
623 while (((*cur >= 'a') && (*cur <= 'z')) ||
624 ((*cur >= 'A') && (*cur <= 'Z')) ||
625 ((*cur >= '0') && (*cur <= '9')) ||
626 (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
627 cur++;
628 if (space)
629 while (IS_BLANK_CH(*cur)(((*cur) == 0x20) || ((0x9 <= (*cur)) && ((*cur) <=
0xa)) || ((*cur) == 0xd))
) cur++;
630 if (*cur == 0)
631 return(0);
632
633try_complex:
634 /*
635 * Second check for chars outside the ASCII range
636 */
637 cur = value;
638 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
639 if (space) {
640 while (IS_BLANK(c)(((c) < 0x100) ? ((((c)) == 0x20) || ((0x9 <= ((c))) &&
(((c)) <= 0xa)) || (((c)) == 0xd)) : 0)
) {
641 cur += l;
642 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
643 }
644 }
645 if (!(IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
|| IS_DIGIT(c)(((c) < 0x100) ? (((0x30 <= ((c))) && (((c)) <=
0x39))) : xmlCharInRange((c), &xmlIsDigitGroup))
|| (c == '.') || (c == ':') ||
646 (c == '-') || (c == '_') || IS_COMBINING(c)(((c) < 0x100) ? 0 : xmlCharInRange((c), &xmlIsCombiningGroup
))
|| IS_EXTENDER(c)(((c) < 0x100) ? ((((c)) == 0xb7)) : xmlCharInRange((c), &
xmlIsExtenderGroup))
))
647 return(1);
648 cur += l;
649 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
650 while (IS_LETTER(c)((((c) < 0x100) ? (((0x41 <= ((c))) && (((c)) <=
0x5a)) || ((0x61 <= ((c))) && (((c)) <= 0x7a))
|| ((0xc0 <= ((c))) && (((c)) <= 0xd6)) || ((0xd8
<= ((c))) && (((c)) <= 0xf6)) || (0xf8 <= (
(c)))) : xmlCharInRange((c), &xmlIsBaseCharGroup)) || (((
c) < 0x100) ? 0 : (((0x4e00 <= (c)) && ((c) <=
0x9fa5)) || ((c) == 0x3007) || ((0x3021 <= (c)) &&
((c) <= 0x3029)))))
|| IS_DIGIT(c)(((c) < 0x100) ? (((0x30 <= ((c))) && (((c)) <=
0x39))) : xmlCharInRange((c), &xmlIsDigitGroup))
|| (c == '.') || (c == ':') ||
651 (c == '-') || (c == '_') || IS_COMBINING(c)(((c) < 0x100) ? 0 : xmlCharInRange((c), &xmlIsCombiningGroup
))
|| IS_EXTENDER(c)(((c) < 0x100) ? ((((c)) == 0xb7)) : xmlCharInRange((c), &
xmlIsExtenderGroup))
) {
652 cur += l;
653 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
654 }
655 if (space) {
656 while (IS_BLANK(c)(((c) < 0x100) ? ((((c)) == 0x20) || ((0x9 <= ((c))) &&
(((c)) <= 0xa)) || (((c)) == 0xd)) : 0)
) {
657 cur += l;
658 c = CUR_SCHAR(cur, l)xmlStringCurrentChar(((void*)0), cur, &l);
659 }
660 }
661 if (c != 0)
662 return(1);
663 return(0);
664}
665#endif /* LIBXML_TREE_ENABLED */
666
667/************************************************************************
668 * *
669 * Allocation and deallocation of basic structures *
670 * *
671 ************************************************************************/
672
673/**
674 * xmlSetBufferAllocationScheme:
675 * @scheme: allocation method to use
676 *
677 * Set the buffer allocation method. Types are
678 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
679 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
680 * improves performance
681 */
682void
683xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
684 if ((scheme == XML_BUFFER_ALLOC_EXACT) ||
685 (scheme == XML_BUFFER_ALLOC_DOUBLEIT))
686 xmlBufferAllocScheme(*(__xmlBufferAllocScheme())) = scheme;
687}
688
689/**
690 * xmlGetBufferAllocationScheme:
691 *
692 * Types are
693 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
694 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
695 * improves performance
696 *
697 * Returns the current allocation scheme
698 */
699xmlBufferAllocationScheme
700xmlGetBufferAllocationScheme(void) {
701 return(xmlBufferAllocScheme(*(__xmlBufferAllocScheme())));
702}
703
704/**
705 * xmlNewNs:
706 * @node: the element carrying the namespace
707 * @href: the URI associated
708 * @prefix: the prefix for the namespace
709 *
710 * Creation of a new Namespace. This function will refuse to create
711 * a namespace with a similar prefix than an existing one present on this
712 * node.
713 * We use href==NULL in the case of an element creation where the namespace
714 * was not defined.
715 * Returns a new namespace pointer or NULL
716 */
717xmlNsPtr
718xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
719 xmlNsPtr cur;
720
721 if ((node != NULL((void*)0)) && (node->type != XML_ELEMENT_NODE))
722 return(NULL((void*)0));
723
724 if ((prefix != NULL((void*)0)) && (xmlStrEqual(prefix, BAD_CAST(xmlChar *) "xml")))
725 return(NULL((void*)0));
726
727 /*
728 * Allocate a new Namespace and fill the fields.
729 */
730 cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
731 if (cur == NULL((void*)0)) {
732 xmlTreeErrMemory("building namespace");
733 return(NULL((void*)0));
734 }
735 memset(cur, 0, sizeof(xmlNs));
736 cur->type = XML_LOCAL_NAMESPACEXML_NAMESPACE_DECL;
737
738 if (href != NULL((void*)0))
739 cur->href = xmlStrdup(href);
740 if (prefix != NULL((void*)0))
741 cur->prefix = xmlStrdup(prefix);
742
743 /*
744 * Add it at the end to preserve parsing order ...
745 * and checks for existing use of the prefix
746 */
747 if (node != NULL((void*)0)) {
748 if (node->nsDef == NULL((void*)0)) {
749 node->nsDef = cur;
750 } else {
751 xmlNsPtr prev = node->nsDef;
752
753 if (((prev->prefix == NULL((void*)0)) && (cur->prefix == NULL((void*)0))) ||
754 (xmlStrEqual(prev->prefix, cur->prefix))) {
755 xmlFreeNs(cur);
756 return(NULL((void*)0));
757 }
758 while (prev->next != NULL((void*)0)) {
759 prev = prev->next;
760 if (((prev->prefix == NULL((void*)0)) && (cur->prefix == NULL((void*)0))) ||
761 (xmlStrEqual(prev->prefix, cur->prefix))) {
762 xmlFreeNs(cur);
763 return(NULL((void*)0));
764 }
765 }
766 prev->next = cur;
767 }
768 }
769 return(cur);
770}
771
772/**
773 * xmlSetNs:
774 * @node: a node in the document
775 * @ns: a namespace pointer
776 *
777 * Associate a namespace to a node, a posteriori.
778 */
779void
780xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
781 if (node == NULL((void*)0)) {
782#ifdef DEBUG_TREE
783 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
784 "xmlSetNs: node == NULL\n");
785#endif
786 return;
787 }
788 node->ns = ns;
789}
790
791/**
792 * xmlFreeNs:
793 * @cur: the namespace pointer
794 *
795 * Free up the structures associated to a namespace
796 */
797void
798xmlFreeNs(xmlNsPtr cur) {
799 if (cur == NULL((void*)0)) {
800#ifdef DEBUG_TREE
801 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
802 "xmlFreeNs : ns == NULL\n");
803#endif
804 return;
805 }
806 if (cur->href != NULL((void*)0)) xmlFree((char *) cur->href);
807 if (cur->prefix != NULL((void*)0)) xmlFree((char *) cur->prefix);
808 xmlFree(cur);
809}
810
811/**
812 * xmlFreeNsList:
813 * @cur: the first namespace pointer
814 *
815 * Free up all the structures associated to the chained namespaces.
816 */
817void
818xmlFreeNsList(xmlNsPtr cur) {
819 xmlNsPtr next;
820 if (cur == NULL((void*)0)) {
821#ifdef DEBUG_TREE
822 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
823 "xmlFreeNsList : ns == NULL\n");
824#endif
825 return;
826 }
827 while (cur != NULL((void*)0)) {
828 next = cur->next;
829 xmlFreeNs(cur);
830 cur = next;
831 }
832}
833
834/**
835 * xmlNewDtd:
836 * @doc: the document pointer
837 * @name: the DTD name
838 * @ExternalID: the external ID
839 * @SystemID: the system ID
840 *
841 * Creation of a new DTD for the external subset. To create an
842 * internal subset, use xmlCreateIntSubset().
843 *
844 * Returns a pointer to the new DTD structure
845 */
846xmlDtdPtr
847xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
848 const xmlChar *ExternalID, const xmlChar *SystemID) {
849 xmlDtdPtr cur;
850
851 if ((doc != NULL((void*)0)) && (doc->extSubset != NULL((void*)0))) {
852#ifdef DEBUG_TREE
853 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
854 "xmlNewDtd(%s): document %s already have a DTD %s\n",
855 /* !!! */ (char *) name, doc->name,
856 /* !!! */ (char *)doc->extSubset->name);
857#endif
858 return(NULL((void*)0));
859 }
860
861 /*
862 * Allocate a new DTD and fill the fields.
863 */
864 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
865 if (cur == NULL((void*)0)) {
866 xmlTreeErrMemory("building DTD");
867 return(NULL((void*)0));
868 }
869 memset(cur, 0 , sizeof(xmlDtd));
870 cur->type = XML_DTD_NODE;
871
872 if (name != NULL((void*)0))
873 cur->name = xmlStrdup(name);
874 if (ExternalID != NULL((void*)0))
875 cur->ExternalID = xmlStrdup(ExternalID);
876 if (SystemID != NULL((void*)0))
877 cur->SystemID = xmlStrdup(SystemID);
878 if (doc != NULL((void*)0))
879 doc->extSubset = cur;
880 cur->doc = doc;
881
882 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
883 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))((xmlNodePtr)cur);
884 return(cur);
885}
886
887/**
888 * xmlGetIntSubset:
889 * @doc: the document pointer
890 *
891 * Get the internal subset of a document
892 * Returns a pointer to the DTD structure or NULL if not found
893 */
894
895xmlDtdPtr
896xmlGetIntSubset(xmlDocPtr doc) {
897 xmlNodePtr cur;
898
899 if (doc == NULL((void*)0))
900 return(NULL((void*)0));
901 cur = doc->children;
902 while (cur != NULL((void*)0)) {
903 if (cur->type == XML_DTD_NODE)
904 return((xmlDtdPtr) cur);
905 cur = cur->next;
906 }
907 return((xmlDtdPtr) doc->intSubset);
908}
909
910/**
911 * xmlCreateIntSubset:
912 * @doc: the document pointer
913 * @name: the DTD name
914 * @ExternalID: the external (PUBLIC) ID
915 * @SystemID: the system ID
916 *
917 * Create the internal subset of a document
918 * Returns a pointer to the new DTD structure
919 */
920xmlDtdPtr
921xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
922 const xmlChar *ExternalID, const xmlChar *SystemID) {
923 xmlDtdPtr cur;
924
925 if ((doc != NULL((void*)0)) && (xmlGetIntSubset(doc) != NULL((void*)0))) {
926#ifdef DEBUG_TREE
927 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
928
929 "xmlCreateIntSubset(): document %s already have an internal subset\n",
930 doc->name);
931#endif
932 return(NULL((void*)0));
933 }
934
935 /*
936 * Allocate a new DTD and fill the fields.
937 */
938 cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
939 if (cur == NULL((void*)0)) {
940 xmlTreeErrMemory("building internal subset");
941 return(NULL((void*)0));
942 }
943 memset(cur, 0, sizeof(xmlDtd));
944 cur->type = XML_DTD_NODE;
945
946 if (name != NULL((void*)0)) {
947 cur->name = xmlStrdup(name);
948 if (cur->name == NULL((void*)0)) {
949 xmlTreeErrMemory("building internal subset");
950 xmlFree(cur);
951 return(NULL((void*)0));
952 }
953 }
954 if (ExternalID != NULL((void*)0)) {
955 cur->ExternalID = xmlStrdup(ExternalID);
956 if (cur->ExternalID == NULL((void*)0)) {
957 xmlTreeErrMemory("building internal subset");
958 if (cur->name != NULL((void*)0))
959 xmlFree((char *)cur->name);
960 xmlFree(cur);
961 return(NULL((void*)0));
962 }
963 }
964 if (SystemID != NULL((void*)0)) {
965 cur->SystemID = xmlStrdup(SystemID);
966 if (cur->SystemID == NULL((void*)0)) {
967 xmlTreeErrMemory("building internal subset");
968 if (cur->name != NULL((void*)0))
969 xmlFree((char *)cur->name);
970 if (cur->ExternalID != NULL((void*)0))
971 xmlFree((char *)cur->ExternalID);
972 xmlFree(cur);
973 return(NULL((void*)0));
974 }
975 }
976 if (doc != NULL((void*)0)) {
977 doc->intSubset = cur;
978 cur->parent = doc;
979 cur->doc = doc;
980 if (doc->children == NULL((void*)0)) {
981 doc->children = (xmlNodePtr) cur;
982 doc->last = (xmlNodePtr) cur;
983 } else {
984 if (doc->type == XML_HTML_DOCUMENT_NODE) {
985 xmlNodePtr prev;
986
987 prev = doc->children;
988 prev->prev = (xmlNodePtr) cur;
989 cur->next = prev;
990 doc->children = (xmlNodePtr) cur;
991 } else {
992 xmlNodePtr next;
993
994 next = doc->children;
995 while ((next != NULL((void*)0)) && (next->type != XML_ELEMENT_NODE))
996 next = next->next;
997 if (next == NULL((void*)0)) {
998 cur->prev = doc->last;
999 cur->prev->next = (xmlNodePtr) cur;
1000 cur->next = NULL((void*)0);
1001 doc->last = (xmlNodePtr) cur;
1002 } else {
1003 cur->next = next;
1004 cur->prev = next->prev;
1005 if (cur->prev == NULL((void*)0))
1006 doc->children = (xmlNodePtr) cur;
1007 else
1008 cur->prev->next = (xmlNodePtr) cur;
1009 next->prev = (xmlNodePtr) cur;
1010 }
1011 }
1012 }
1013 }
1014
1015 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
1016 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))((xmlNodePtr)cur);
1017 return(cur);
1018}
1019
1020/**
1021 * DICT_FREE:
1022 * @str: a string
1023 *
1024 * Free a string if it is not owned by the "dict" dictionnary in the
1025 * current scope
1026 */
1027#define DICT_FREE(str)if ((str) && ((!dict) || (xmlDictOwns(dict, (const xmlChar
*)(str)) == 0))) xmlFree((char *)(str));
\
1028 if ((str) && ((!dict) || \
1029 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
1030 xmlFree((char *)(str));
1031
1032
1033/**
1034 * DICT_COPY:
1035 * @str: a string
1036 *
1037 * Copy a string using a "dict" dictionnary in the current scope,
1038 * if availabe.
1039 */
1040#define DICT_COPY(str, cpy)if (str) { if (dict) { if (xmlDictOwns(dict, (const xmlChar *
)(str))) cpy = (xmlChar *) (str); else cpy = (xmlChar *) xmlDictLookup
((dict), (const xmlChar *)(str), -1); } else cpy = xmlStrdup(
(const xmlChar *)(str)); }
\
1041 if (str) { \
1042 if (dict) { \
1043 if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1044 cpy = (xmlChar *) (str); \
1045 else \
1046 cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1047 } else \
1048 cpy = xmlStrdup((const xmlChar *)(str)); }
1049
1050/**
1051 * DICT_CONST_COPY:
1052 * @str: a string
1053 *
1054 * Copy a string using a "dict" dictionnary in the current scope,
1055 * if availabe.
1056 */
1057#define DICT_CONST_COPY(str, cpy)if (str) { if (dict) { if (xmlDictOwns(dict, (const xmlChar *
)(str))) cpy = (const xmlChar *) (str); else cpy = xmlDictLookup
((dict), (const xmlChar *)(str), -1); } else cpy = (const xmlChar
*) xmlStrdup((const xmlChar *)(str)); }
\
1058 if (str) { \
1059 if (dict) { \
1060 if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1061 cpy = (const xmlChar *) (str); \
1062 else \
1063 cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1064 } else \
1065 cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }
1066
1067
1068/**
1069 * xmlFreeDtd:
1070 * @cur: the DTD structure to free up
1071 *
1072 * Free a DTD structure.
1073 */
1074void
1075xmlFreeDtd(xmlDtdPtr cur) {
1076 xmlDictPtr dict = NULL((void*)0);
1077
1078 if (cur == NULL((void*)0)) {
1079 return;
1080 }
1081 if (cur->doc != NULL((void*)0)) dict = cur->doc->dict;
1082
1083 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue(*(__xmlDeregisterNodeDefaultValue()))))
1084 xmlDeregisterNodeDefaultValue(*(__xmlDeregisterNodeDefaultValue()))((xmlNodePtr)cur);
1085
1086 if (cur->children != NULL((void*)0)) {
1087 xmlNodePtr next, c = cur->children;
1088
1089 /*
1090 * Cleanup all nodes which are not part of the specific lists
1091 * of notations, elements, attributes and entities.
1092 */
1093 while (c != NULL((void*)0)) {
1094 next = c->next;
1095 if ((c->type != XML_NOTATION_NODE) &&
1096 (c->type != XML_ELEMENT_DECL) &&
1097 (c->type != XML_ATTRIBUTE_DECL) &&
1098 (c->type != XML_ENTITY_DECL)) {
1099 xmlUnlinkNode(c);
1100 xmlFreeNode(c);
1101 }
1102 c = next;
1103 }
1104 }
1105 DICT_FREE(cur->name)if ((cur->name) && ((!dict) || (xmlDictOwns(dict, (
const xmlChar *)(cur->name)) == 0))) xmlFree((char *)(cur->
name));
1106 DICT_FREE(cur->SystemID)if ((cur->SystemID) && ((!dict) || (xmlDictOwns(dict
, (const xmlChar *)(cur->SystemID)) == 0))) xmlFree((char *
)(cur->SystemID));
1107 DICT_FREE(cur->ExternalID)if ((cur->ExternalID) && ((!dict) || (xmlDictOwns(
dict, (const xmlChar *)(cur->ExternalID)) == 0))) xmlFree(
(char *)(cur->ExternalID));
1108 /* TODO !!! */
1109 if (cur->notations != NULL((void*)0))
1110 xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
1111
1112 if (cur->elements != NULL((void*)0))
1113 xmlFreeElementTable((xmlElementTablePtr) cur->elements);
1114 if (cur->attributes != NULL((void*)0))
1115 xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
1116 if (cur->entities != NULL((void*)0))
1117 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
1118 if (cur->pentities != NULL((void*)0))
1119 xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->pentities);
1120
1121 xmlFree(cur);
1122}
1123
1124/**
1125 * xmlNewDoc:
1126 * @version: xmlChar string giving the version of XML "1.0"
1127 *
1128 * Creates a new XML document
1129 *
1130 * Returns a new document
1131 */
1132xmlDocPtr
1133xmlNewDoc(const xmlChar *version) {
1134 xmlDocPtr cur;
1135
1136 if (version == NULL((void*)0))
1137 version = (const xmlChar *) "1.0";
1138
1139 /*
1140 * Allocate a new document and fill the fields.
1141 */
1142 cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
1143 if (cur == NULL((void*)0)) {
1144 xmlTreeErrMemory("building doc");
1145 return(NULL((void*)0));
1146 }
1147 memset(cur, 0, sizeof(xmlDoc));
1148 cur->type = XML_DOCUMENT_NODE;
1149
1150 cur->version = xmlStrdup(version);
1151 if (cur->version == NULL((void*)0)) {
1152 xmlTreeErrMemory("building doc");
1153 xmlFree(cur);
1154 return(NULL((void*)0));
1155 }
1156 cur->standalone = -1;
1157 cur->compression = -1; /* not initialized */
1158 cur->doc = cur;
1159 cur->parseFlags = 0;
1160 cur->properties = XML_DOC_USERBUILT;
1161 /*
1162 * The in memory encoding is always UTF8
1163 * This field will never change and would
1164 * be obsolete if not for binary compatibility.
1165 */
1166 cur->charset = XML_CHAR_ENCODING_UTF8;
1167
1168 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
1169 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))((xmlNodePtr)cur);
1170 return(cur);
1171}
1172
1173/**
1174 * xmlFreeDoc:
1175 * @cur: pointer to the document
1176 *
1177 * Free up all the structures used by a document, tree included.
1178 */
1179void
1180xmlFreeDoc(xmlDocPtr cur) {
1181 xmlDtdPtr extSubset, intSubset;
1182 xmlDictPtr dict = NULL((void*)0);
1183
1184 if (cur == NULL((void*)0)) {
1185#ifdef DEBUG_TREE
1186 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
1187 "xmlFreeDoc : document == NULL\n");
1188#endif
1189 return;
1190 }
1191#ifdef LIBXML_DEBUG_RUNTIME
1192#ifdef LIBXML_DEBUG_ENABLED
1193 xmlDebugCheckDocument(stderrstderr, cur);
1194#endif
1195#endif
1196
1197 if (cur != NULL((void*)0)) dict = cur->dict;
1198
1199 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue(*(__xmlDeregisterNodeDefaultValue()))))
1200 xmlDeregisterNodeDefaultValue(*(__xmlDeregisterNodeDefaultValue()))((xmlNodePtr)cur);
1201
1202 /*
1203 * Do this before freeing the children list to avoid ID lookups
1204 */
1205 if (cur->ids != NULL((void*)0)) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
1206 cur->ids = NULL((void*)0);
1207 if (cur->refs != NULL((void*)0)) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
1208 cur->refs = NULL((void*)0);
1209 extSubset = cur->extSubset;
1210 intSubset = cur->intSubset;
1211 if (intSubset == extSubset)
1212 extSubset = NULL((void*)0);
1213 if (extSubset != NULL((void*)0)) {
1214 xmlUnlinkNode((xmlNodePtr) cur->extSubset);
1215 cur->extSubset = NULL((void*)0);
1216 xmlFreeDtd(extSubset);
1217 }
1218 if (intSubset != NULL((void*)0)) {
1219 xmlUnlinkNode((xmlNodePtr) cur->intSubset);
1220 cur->intSubset = NULL((void*)0);
1221 xmlFreeDtd(intSubset);
1222 }
1223
1224 if (cur->children != NULL((void*)0)) xmlFreeNodeList(cur->children);
1225 if (cur->oldNs != NULL((void*)0)) xmlFreeNsList(cur->oldNs);
1226
1227 DICT_FREE(cur->version)if ((cur->version) && ((!dict) || (xmlDictOwns(dict
, (const xmlChar *)(cur->version)) == 0))) xmlFree((char *
)(cur->version));
1228 DICT_FREE(cur->name)if ((cur->name) && ((!dict) || (xmlDictOwns(dict, (
const xmlChar *)(cur->name)) == 0))) xmlFree((char *)(cur->
name));
1229 DICT_FREE(cur->encoding)if ((cur->encoding) && ((!dict) || (xmlDictOwns(dict
, (const xmlChar *)(cur->encoding)) == 0))) xmlFree((char *
)(cur->encoding));
1230 DICT_FREE(cur->URL)if ((cur->URL) && ((!dict) || (xmlDictOwns(dict, (
const xmlChar *)(cur->URL)) == 0))) xmlFree((char *)(cur->
URL));
1231 xmlFree(cur);
1232 if (dict) xmlDictFree(dict);
1233}
1234
1235/**
1236 * xmlStringLenGetNodeList:
1237 * @doc: the document
1238 * @value: the value of the text
1239 * @len: the length of the string value
1240 *
1241 * Parse the value string and build the node list associated. Should
1242 * produce a flat tree with only TEXTs and ENTITY_REFs.
1243 * Returns a pointer to the first child
1244 */
1245xmlNodePtr
1246xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
1247 xmlNodePtr ret = NULL((void*)0), last = NULL((void*)0);
1248 xmlNodePtr node;
1249 xmlChar *val;
1250 const xmlChar *cur = value, *end = cur + len;
1251 const xmlChar *q;
1252 xmlEntityPtr ent;
1253
1254 if (value == NULL((void*)0)) return(NULL((void*)0));
1255
1256 q = cur;
1257 while ((cur < end) && (*cur != 0)) {
1258 if (cur[0] == '&') {
1259 int charval = 0;
1260 xmlChar tmp;
1261
1262 /*
1263 * Save the current text.
1264 */
1265 if (cur != q) {
1266 if ((last != NULL((void*)0)) && (last->type == XML_TEXT_NODE)) {
1267 xmlNodeAddContentLen(last, q, cur - q);
1268 } else {
1269 node = xmlNewDocTextLen(doc, q, cur - q);
1270 if (node == NULL((void*)0)) return(ret);
1271 if (last == NULL((void*)0))
1272 last = ret = node;
1273 else {
1274 last->next = node;
1275 node->prev = last;
1276 last = node;
1277 }
1278 }
1279 }
1280 q = cur;
1281 if ((cur + 2 < end) && (cur[1] == '#') && (cur[2] == 'x')) {
1282 cur += 3;
1283 if (cur < end)
1284 tmp = *cur;
1285 else
1286 tmp = 0;
1287 while (tmp != ';') { /* Non input consuming loop */
1288 if ((tmp >= '0') && (tmp <= '9'))
1289 charval = charval * 16 + (tmp - '0');
1290 else if ((tmp >= 'a') && (tmp <= 'f'))
1291 charval = charval * 16 + (tmp - 'a') + 10;
1292 else if ((tmp >= 'A') && (tmp <= 'F'))
1293 charval = charval * 16 + (tmp - 'A') + 10;
1294 else {
1295 xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
1296 NULL((void*)0));
1297 charval = 0;
1298 break;
1299 }
1300 cur++;
1301 if (cur < end)
1302 tmp = *cur;
1303 else
1304 tmp = 0;
1305 }
1306 if (tmp == ';')
1307 cur++;
1308 q = cur;
1309 } else if ((cur + 1 < end) && (cur[1] == '#')) {
1310 cur += 2;
1311 if (cur < end)
1312 tmp = *cur;
1313 else
1314 tmp = 0;
1315 while (tmp != ';') { /* Non input consuming loops */
1316 if ((tmp >= '0') && (tmp <= '9'))
1317 charval = charval * 10 + (tmp - '0');
1318 else {
1319 xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
1320 NULL((void*)0));
1321 charval = 0;
1322 break;
1323 }
1324 cur++;
1325 if (cur < end)
1326 tmp = *cur;
1327 else
1328 tmp = 0;
1329 }
1330 if (tmp == ';')
1331 cur++;
1332 q = cur;
1333 } else {
1334 /*
1335 * Read the entity string
1336 */
1337 cur++;
1338 q = cur;
1339 while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++;
1340 if ((cur >= end) || (*cur == 0)) {
1341 xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, (xmlNodePtr) doc,
1342 (const char *) q);
1343 return(ret);
1344 }
1345 if (cur != q) {
1346 /*
1347 * Predefined entities don't generate nodes
1348 */
1349 val = xmlStrndup(q, cur - q);
1350 ent = xmlGetDocEntity(doc, val);
1351 if ((ent != NULL((void*)0)) &&
1352 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1353 if (last == NULL((void*)0)) {
1354 node = xmlNewDocText(doc, ent->content);
1355 last = ret = node;
1356 } else if (last->type != XML_TEXT_NODE) {
1357 node = xmlNewDocText(doc, ent->content);
1358 last = xmlAddNextSibling(last, node);
1359 } else
1360 xmlNodeAddContent(last, ent->content);
1361
1362 } else {
1363 /*
1364 * Create a new REFERENCE_REF node
1365 */
1366 node = xmlNewReference(doc, val);
1367 if (node == NULL((void*)0)) {
1368 if (val != NULL((void*)0)) xmlFree(val);
1369 return(ret);
1370 }
1371 else if ((ent != NULL((void*)0)) && (ent->children == NULL((void*)0))) {
1372 xmlNodePtr temp;
1373
1374 ent->children = xmlStringGetNodeList(doc,
1375 (const xmlChar*)node->content);
1376 ent->owner = 1;
1377 temp = ent->children;
1378 while (temp) {
1379 temp->parent = (xmlNodePtr)ent;
1380 ent->last = temp;
1381 temp = temp->next;
1382 }
1383 }
1384 if (last == NULL((void*)0)) {
1385 last = ret = node;
1386 } else {
1387 last = xmlAddNextSibling(last, node);
1388 }
1389 }
1390 xmlFree(val);
1391 }
1392 cur++;
1393 q = cur;
1394 }
1395 if (charval != 0) {
1396 xmlChar buf[10];
1397 int l;
1398
1399 l = xmlCopyCharMultiByte(buf, charval);
1400 buf[l] = 0;
1401 node = xmlNewDocText(doc, buf);
1402 if (node != NULL((void*)0)) {
1403 if (last == NULL((void*)0)) {
1404 last = ret = node;
1405 } else {
1406 last = xmlAddNextSibling(last, node);
1407 }
1408 }
1409 charval = 0;
1410 }
1411 } else
1412 cur++;
1413 }
1414 if ((cur != q) || (ret == NULL((void*)0))) {
1415 /*
1416 * Handle the last piece of text.
1417 */
1418 if ((last != NULL((void*)0)) && (last->type == XML_TEXT_NODE)) {
1419 xmlNodeAddContentLen(last, q, cur - q);
1420 } else {
1421 node = xmlNewDocTextLen(doc, q, cur - q);
1422 if (node == NULL((void*)0)) return(ret);
1423 if (last == NULL((void*)0)) {
1424 last = ret = node;
Value stored to 'last' is never read
1425 } else {
1426 last = xmlAddNextSibling(last, node);
1427 }
1428 }
1429 }
1430 return(ret);
1431}
1432
1433/**
1434 * xmlStringGetNodeList:
1435 * @doc: the document
1436 * @value: the value of the attribute
1437 *
1438 * Parse the value string and build the node list associated. Should
1439 * produce a flat tree with only TEXTs and ENTITY_REFs.
1440 * Returns a pointer to the first child
1441 */
1442xmlNodePtr
1443xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
1444 xmlNodePtr ret = NULL((void*)0), last = NULL((void*)0);
1445 xmlNodePtr node;
1446 xmlChar *val;
1447 const xmlChar *cur = value;
1448 const xmlChar *q;
1449 xmlEntityPtr ent;
1450
1451 if (value == NULL((void*)0)) return(NULL((void*)0));
1452
1453 q = cur;
1454 while (*cur != 0) {
1455 if (cur[0] == '&') {
1456 int charval = 0;
1457 xmlChar tmp;
1458
1459 /*
1460 * Save the current text.
1461 */
1462 if (cur != q) {
1463 if ((last != NULL((void*)0)) && (last->type == XML_TEXT_NODE)) {
1464 xmlNodeAddContentLen(last, q, cur - q);
1465 } else {
1466 node = xmlNewDocTextLen(doc, q, cur - q);
1467 if (node == NULL((void*)0)) return(ret);
1468 if (last == NULL((void*)0))
1469 last = ret = node;
1470 else {
1471 last->next = node;
1472 node->prev = last;
1473 last = node;
1474 }
1475 }
1476 }
1477 q = cur;
1478 if ((cur[1] == '#') && (cur[2] == 'x')) {
1479 cur += 3;
1480 tmp = *cur;
1481 while (tmp != ';') { /* Non input consuming loop */
1482 if ((tmp >= '0') && (tmp <= '9'))
1483 charval = charval * 16 + (tmp - '0');
1484 else if ((tmp >= 'a') && (tmp <= 'f'))
1485 charval = charval * 16 + (tmp - 'a') + 10;
1486 else if ((tmp >= 'A') && (tmp <= 'F'))
1487 charval = charval * 16 + (tmp - 'A') + 10;
1488 else {
1489 xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
1490 NULL((void*)0));
1491 charval = 0;
1492 break;
1493 }
1494 cur++;
1495 tmp = *cur;
1496 }
1497 if (tmp == ';')
1498 cur++;
1499 q = cur;
1500 } else if (cur[1] == '#') {
1501 cur += 2;
1502 tmp = *cur;
1503 while (tmp != ';') { /* Non input consuming loops */
1504 if ((tmp >= '0') && (tmp <= '9'))
1505 charval = charval * 10 + (tmp - '0');
1506 else {
1507 xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
1508 NULL((void*)0));
1509 charval = 0;
1510 break;
1511 }
1512 cur++;
1513 tmp = *cur;
1514 }
1515 if (tmp == ';')
1516 cur++;
1517 q = cur;
1518 } else {
1519 /*
1520 * Read the entity string
1521 */
1522 cur++;
1523 q = cur;
1524 while ((*cur != 0) && (*cur != ';')) cur++;
1525 if (*cur == 0) {
1526 xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY,
1527 (xmlNodePtr) doc, (const char *) q);
1528 return(ret);
1529 }
1530 if (cur != q) {
1531 /*
1532 * Predefined entities don't generate nodes
1533 */
1534 val = xmlStrndup(q, cur - q);
1535 ent = xmlGetDocEntity(doc, val);
1536 if ((ent != NULL((void*)0)) &&
1537 (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1538 if (last == NULL((void*)0)) {
1539 node = xmlNewDocText(doc, ent->content);
1540 last = ret = node;
1541 } else if (last->type != XML_TEXT_NODE) {
1542 node = xmlNewDocText(doc, ent->content);
1543 last = xmlAddNextSibling(last, node);
1544 } else
1545 xmlNodeAddContent(last, ent->content);
1546
1547 } else {
1548 /*
1549 * Create a new REFERENCE_REF node
1550 */
1551 node = xmlNewReference(doc, val);
1552 if (node == NULL((void*)0)) {
1553 if (val != NULL((void*)0)) xmlFree(val);
1554 return(ret);
1555 }
1556 else if ((ent != NULL((void*)0)) && (ent->children == NULL((void*)0))) {
1557 xmlNodePtr temp;
1558
1559 ent->children = xmlStringGetNodeList(doc,
1560 (const xmlChar*)node->content);
1561 ent->owner = 1;
1562 temp = ent->children;
1563 while (temp) {
1564 temp->parent = (xmlNodePtr)ent;
1565 temp = temp->next;
1566 }
1567 }
1568 if (last == NULL((void*)0)) {
1569 last = ret = node;
1570 } else {
1571 last = xmlAddNextSibling(last, node);
1572 }
1573 }
1574 xmlFree(val);
1575 }
1576 cur++;
1577 q = cur;
1578 }
1579 if (charval != 0) {
1580 xmlChar buf[10];
1581 int len;
1582
1583 len = xmlCopyCharMultiByte(buf, charval);
1584 buf[len] = 0;
1585 node = xmlNewDocText(doc, buf);
1586 if (node != NULL((void*)0)) {
1587 if (last == NULL((void*)0)) {
1588 last = ret = node;
1589 } else {
1590 last = xmlAddNextSibling(last, node);
1591 }
1592 }
1593
1594 charval = 0;
1595 }
1596 } else
1597 cur++;
1598 }
1599 if ((cur != q) || (ret == NULL((void*)0))) {
1600 /*
1601 * Handle the last piece of text.
1602 */
1603 if ((last != NULL((void*)0)) && (last->type == XML_TEXT_NODE)) {
1604 xmlNodeAddContentLen(last, q, cur - q);
1605 } else {
1606 node = xmlNewDocTextLen(doc, q, cur - q);
1607 if (node == NULL((void*)0)) return(ret);
1608 if (last == NULL((void*)0)) {
1609 last = ret = node;
1610 } else {
1611 last = xmlAddNextSibling(last, node);
1612 }
1613 }
1614 }
1615 return(ret);
1616}
1617
1618/**
1619 * xmlNodeListGetString:
1620 * @doc: the document
1621 * @list: a Node list
1622 * @inLine: should we replace entity contents or show their external form
1623 *
1624 * Build the string equivalent to the text contained in the Node list
1625 * made of TEXTs and ENTITY_REFs
1626 *
1627 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1628 */
1629xmlChar *
1630xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine)
1631{
1632 xmlNodePtr node = list;
1633 xmlChar *ret = NULL((void*)0);
1634 xmlEntityPtr ent;
1635
1636 if (list == NULL((void*)0))
1637 return (NULL((void*)0));
1638
1639 while (node != NULL((void*)0)) {
1640 if ((node->type == XML_TEXT_NODE) ||
1641 (node->type == XML_CDATA_SECTION_NODE)) {
1642 if (inLine) {
1643 ret = xmlStrcat(ret, node->content);
1644 } else {
1645 xmlChar *buffer;
1646
1647 buffer = xmlEncodeEntitiesReentrant(doc, node->content);
1648 if (buffer != NULL((void*)0)) {
1649 ret = xmlStrcat(ret, buffer);
1650 xmlFree(buffer);
1651 }
1652 }
1653 } else if (node->type == XML_ENTITY_REF_NODE) {
1654 if (inLine) {
1655 ent = xmlGetDocEntity(doc, node->name);
1656 if (ent != NULL((void*)0)) {
1657 xmlChar *buffer;
1658
1659 /* an entity content can be any "well balanced chunk",
1660 * i.e. the result of the content [43] production:
1661 * http://www.w3.org/TR/REC-xml#NT-content.
1662 * So it can contain text, CDATA section or nested
1663 * entity reference nodes (among others).
1664 * -> we recursive call xmlNodeListGetString()
1665 * which handles these types */
1666 buffer = xmlNodeListGetString(doc, ent->children, 1);
1667 if (buffer != NULL((void*)0)) {
1668 ret = xmlStrcat(ret, buffer);
1669 xmlFree(buffer);
1670 }
1671 } else {
1672 ret = xmlStrcat(ret, node->content);
1673 }
1674 } else {
1675 xmlChar buf[2];
1676
1677 buf[0] = '&';
1678 buf[1] = 0;
1679 ret = xmlStrncat(ret, buf, 1);
1680 ret = xmlStrcat(ret, node->name);
1681 buf[0] = ';';
1682 buf[1] = 0;
1683 ret = xmlStrncat(ret, buf, 1);
1684 }
1685 }
1686#if 0
1687 else {
1688 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
1689 "xmlGetNodeListString : invalid node type %d\n",
1690 node->type);
1691 }
1692#endif
1693 node = node->next;
1694 }
1695 return (ret);
1696}
1697
1698#ifdef LIBXML_TREE_ENABLED
1699/**
1700 * xmlNodeListGetRawString:
1701 * @doc: the document
1702 * @list: a Node list
1703 * @inLine: should we replace entity contents or show their external form
1704 *
1705 * Builds the string equivalent to the text contained in the Node list
1706 * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
1707 * this function doesn't do any character encoding handling.
1708 *
1709 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1710 */
1711xmlChar *
1712xmlNodeListGetRawString(xmlDocPtr doc, xmlNodePtr list, int inLine)
1713{
1714 xmlNodePtr node = list;
1715 xmlChar *ret = NULL((void*)0);
1716 xmlEntityPtr ent;
1717
1718 if (list == NULL((void*)0))
1719 return (NULL((void*)0));
1720
1721 while (node != NULL((void*)0)) {
1722 if ((node->type == XML_TEXT_NODE) ||
1723 (node->type == XML_CDATA_SECTION_NODE)) {
1724 if (inLine) {
1725 ret = xmlStrcat(ret, node->content);
1726 } else {
1727 xmlChar *buffer;
1728
1729 buffer = xmlEncodeSpecialChars(doc, node->content);
1730 if (buffer != NULL((void*)0)) {
1731 ret = xmlStrcat(ret, buffer);
1732 xmlFree(buffer);
1733 }
1734 }
1735 } else if (node->type == XML_ENTITY_REF_NODE) {
1736 if (inLine) {
1737 ent = xmlGetDocEntity(doc, node->name);
1738 if (ent != NULL((void*)0)) {
1739 xmlChar *buffer;
1740
1741 /* an entity content can be any "well balanced chunk",
1742 * i.e. the result of the content [43] production:
1743 * http://www.w3.org/TR/REC-xml#NT-content.
1744 * So it can contain text, CDATA section or nested
1745 * entity reference nodes (among others).
1746 * -> we recursive call xmlNodeListGetRawString()
1747 * which handles these types */
1748 buffer =
1749 xmlNodeListGetRawString(doc, ent->children, 1);
1750 if (buffer != NULL((void*)0)) {
1751 ret = xmlStrcat(ret, buffer);
1752 xmlFree(buffer);
1753 }
1754 } else {
1755 ret = xmlStrcat(ret, node->content);
1756 }
1757 } else {
1758 xmlChar buf[2];
1759
1760 buf[0] = '&';
1761 buf[1] = 0;
1762 ret = xmlStrncat(ret, buf, 1);
1763 ret = xmlStrcat(ret, node->name);
1764 buf[0] = ';';
1765 buf[1] = 0;
1766 ret = xmlStrncat(ret, buf, 1);
1767 }
1768 }
1769#if 0
1770 else {
1771 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
1772 "xmlGetNodeListString : invalid node type %d\n",
1773 node->type);
1774 }
1775#endif
1776 node = node->next;
1777 }
1778 return (ret);
1779}
1780#endif /* LIBXML_TREE_ENABLED */
1781
1782static xmlAttrPtr
1783xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
1784 const xmlChar * name, const xmlChar * value,
1785 int eatname)
1786{
1787 xmlAttrPtr cur;
1788 xmlDocPtr doc = NULL((void*)0);
1789
1790 if ((node != NULL((void*)0)) && (node->type != XML_ELEMENT_NODE)) {
1791 if ((eatname == 1) &&
1792 ((node->doc == NULL((void*)0)) ||
1793 (!(xmlDictOwns(node->doc->dict, name)))))
1794 xmlFree((xmlChar *) name);
1795 return (NULL((void*)0));
1796 }
1797
1798 /*
1799 * Allocate a new property and fill the fields.
1800 */
1801 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1802 if (cur == NULL((void*)0)) {
1803 if ((eatname == 1) &&
1804 ((node->doc == NULL((void*)0)) ||
1805 (!(xmlDictOwns(node->doc->dict, name)))))
1806 xmlFree((xmlChar *) name);
1807 xmlTreeErrMemory("building attribute");
1808 return (NULL((void*)0));
1809 }
1810 memset(cur, 0, sizeof(xmlAttr));
1811 cur->type = XML_ATTRIBUTE_NODE;
1812
1813 cur->parent = node;
1814 if (node != NULL((void*)0)) {
1815 doc = node->doc;
1816 cur->doc = doc;
1817 }
1818 cur->ns = ns;
1819
1820 if (eatname == 0) {
1821 if ((doc != NULL((void*)0)) && (doc->dict != NULL((void*)0)))
1822 cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
1823 else
1824 cur->name = xmlStrdup(name);
1825 } else
1826 cur->name = name;
1827
1828 if (value != NULL((void*)0)) {
1829 xmlNodePtr tmp;
1830
1831 if(!xmlCheckUTF8(value)) {
1832 xmlTreeErr(XML_TREE_NOT_UTF8, (xmlNodePtr) doc,
1833 NULL((void*)0));
1834 if (doc != NULL((void*)0))
1835 doc->encoding = xmlStrdup(BAD_CAST(xmlChar *) "ISO-8859-1");
1836 }
1837 cur->children = xmlNewDocText(doc, value);
1838 cur->last = NULL((void*)0);
1839 tmp = cur->children;
1840 while (tmp != NULL((void*)0)) {
1841 tmp->parent = (xmlNodePtr) cur;
1842 if (tmp->next == NULL((void*)0))
1843 cur->last = tmp;
1844 tmp = tmp->next;
1845 }
1846 }
1847
1848 /*
1849 * Add it at the end to preserve parsing order ...
1850 */
1851 if (node != NULL((void*)0)) {
1852 if (node->properties == NULL((void*)0)) {
1853 node->properties = cur;
1854 } else {
1855 xmlAttrPtr prev = node->properties;
1856
1857 while (prev->next != NULL((void*)0))
1858 prev = prev->next;
1859 prev->next = cur;
1860 cur->prev = prev;
1861 }
1862 }
1863
1864 if ((value != NULL((void*)0)) &&
1865 (xmlIsID((node == NULL((void*)0)) ? NULL((void*)0) : node->doc, node, cur) == 1))
1866 xmlAddID(NULL((void*)0), node->doc, value, cur);
1867
1868 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
1869 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))((xmlNodePtr) cur);
1870 return (cur);
1871}
1872
1873#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
1874 defined(LIBXML_SCHEMAS_ENABLED)
1875/**
1876 * xmlNewProp:
1877 * @node: the holding node
1878 * @name: the name of the attribute
1879 * @value: the value of the attribute
1880 *
1881 * Create a new property carried by a node.
1882 * Returns a pointer to the attribute
1883 */
1884xmlAttrPtr
1885xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
1886
1887 if (name == NULL((void*)0)) {
1888#ifdef DEBUG_TREE
1889 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
1890 "xmlNewProp : name == NULL\n");
1891#endif
1892 return(NULL((void*)0));
1893 }
1894
1895 return xmlNewPropInternal(node, NULL((void*)0), name, value, 0);
1896}
1897#endif /* LIBXML_TREE_ENABLED */
1898
1899/**
1900 * xmlNewNsProp:
1901 * @node: the holding node
1902 * @ns: the namespace
1903 * @name: the name of the attribute
1904 * @value: the value of the attribute
1905 *
1906 * Create a new property tagged with a namespace and carried by a node.
1907 * Returns a pointer to the attribute
1908 */
1909xmlAttrPtr
1910xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
1911 const xmlChar *value) {
1912
1913 if (name == NULL((void*)0)) {
1914#ifdef DEBUG_TREE
1915 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
1916 "xmlNewNsProp : name == NULL\n");
1917#endif
1918 return(NULL((void*)0));
1919 }
1920
1921 return xmlNewPropInternal(node, ns, name, value, 0);
1922}
1923
1924/**
1925 * xmlNewNsPropEatName:
1926 * @node: the holding node
1927 * @ns: the namespace
1928 * @name: the name of the attribute
1929 * @value: the value of the attribute
1930 *
1931 * Create a new property tagged with a namespace and carried by a node.
1932 * Returns a pointer to the attribute
1933 */
1934xmlAttrPtr
1935xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name,
1936 const xmlChar *value) {
1937
1938 if (name == NULL((void*)0)) {
1939#ifdef DEBUG_TREE
1940 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
1941 "xmlNewNsPropEatName : name == NULL\n");
1942#endif
1943 return(NULL((void*)0));
1944 }
1945
1946 return xmlNewPropInternal(node, ns, name, value, 1);
1947}
1948
1949/**
1950 * xmlNewDocProp:
1951 * @doc: the document
1952 * @name: the name of the attribute
1953 * @value: the value of the attribute
1954 *
1955 * Create a new property carried by a document.
1956 * Returns a pointer to the attribute
1957 */
1958xmlAttrPtr
1959xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
1960 xmlAttrPtr cur;
1961
1962 if (name == NULL((void*)0)) {
1963#ifdef DEBUG_TREE
1964 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
1965 "xmlNewDocProp : name == NULL\n");
1966#endif
1967 return(NULL((void*)0));
1968 }
1969
1970 /*
1971 * Allocate a new property and fill the fields.
1972 */
1973 cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1974 if (cur == NULL((void*)0)) {
1975 xmlTreeErrMemory("building attribute");
1976 return(NULL((void*)0));
1977 }
1978 memset(cur, 0, sizeof(xmlAttr));
1979 cur->type = XML_ATTRIBUTE_NODE;
1980
1981 if ((doc != NULL((void*)0)) && (doc->dict != NULL((void*)0)))
1982 cur->name = xmlDictLookup(doc->dict, name, -1);
1983 else
1984 cur->name = xmlStrdup(name);
1985 cur->doc = doc;
1986 if (value != NULL((void*)0)) {
1987 xmlNodePtr tmp;
1988
1989 cur->children = xmlStringGetNodeList(doc, value);
1990 cur->last = NULL((void*)0);
1991
1992 tmp = cur->children;
1993 while (tmp != NULL((void*)0)) {
1994 tmp->parent = (xmlNodePtr) cur;
1995 if (tmp->next == NULL((void*)0))
1996 cur->last = tmp;
1997 tmp = tmp->next;
1998 }
1999 }
2000
2001 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
2002 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))((xmlNodePtr)cur);
2003 return(cur);
2004}
2005
2006/**
2007 * xmlFreePropList:
2008 * @cur: the first property in the list
2009 *
2010 * Free a property and all its siblings, all the children are freed too.
2011 */
2012void
2013xmlFreePropList(xmlAttrPtr cur) {
2014 xmlAttrPtr next;
2015 if (cur == NULL((void*)0)) return;
2016 while (cur != NULL((void*)0)) {
2017 next = cur->next;
2018 xmlFreeProp(cur);
2019 cur = next;
2020 }
2021}
2022
2023/**
2024 * xmlFreeProp:
2025 * @cur: an attribute
2026 *
2027 * Free one attribute, all the content is freed too
2028 */
2029void
2030xmlFreeProp(xmlAttrPtr cur) {
2031 xmlDictPtr dict = NULL((void*)0);
2032 if (cur == NULL((void*)0)) return;
2033
2034 if (cur->doc != NULL((void*)0)) dict = cur->doc->dict;
2035
2036 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue(*(__xmlDeregisterNodeDefaultValue()))))
2037 xmlDeregisterNodeDefaultValue(*(__xmlDeregisterNodeDefaultValue()))((xmlNodePtr)cur);
2038
2039 /* Check for ID removal -> leading to invalid references ! */
2040 if ((cur->doc != NULL((void*)0)) && (cur->atype == XML_ATTRIBUTE_ID)) {
2041 xmlRemoveID(cur->doc, cur);
2042 }
2043 if (cur->children != NULL((void*)0)) xmlFreeNodeList(cur->children);
2044 DICT_FREE(cur->name)if ((cur->name) && ((!dict) || (xmlDictOwns(dict, (
const xmlChar *)(cur->name)) == 0))) xmlFree((char *)(cur->
name));
2045 xmlFree(cur);
2046}
2047
2048/**
2049 * xmlRemoveProp:
2050 * @cur: an attribute
2051 *
2052 * Unlink and free one attribute, all the content is freed too
2053 * Note this doesn't work for namespace definition attributes
2054 *
2055 * Returns 0 if success and -1 in case of error.
2056 */
2057int
2058xmlRemoveProp(xmlAttrPtr cur) {
2059 xmlAttrPtr tmp;
2060 if (cur == NULL((void*)0)) {
2061#ifdef DEBUG_TREE
2062 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2063 "xmlRemoveProp : cur == NULL\n");
2064#endif
2065 return(-1);
2066 }
2067 if (cur->parent == NULL((void*)0)) {
2068#ifdef DEBUG_TREE
2069 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2070 "xmlRemoveProp : cur->parent == NULL\n");
2071#endif
2072 return(-1);
2073 }
2074 tmp = cur->parent->properties;
2075 if (tmp == cur) {
2076 cur->parent->properties = cur->next;
2077 if (cur->next != NULL((void*)0))
2078 cur->next->prev = NULL((void*)0);
2079 xmlFreeProp(cur);
2080 return(0);
2081 }
2082 while (tmp != NULL((void*)0)) {
2083 if (tmp->next == cur) {
2084 tmp->next = cur->next;
2085 if (tmp->next != NULL((void*)0))
2086 tmp->next->prev = tmp;
2087 xmlFreeProp(cur);
2088 return(0);
2089 }
2090 tmp = tmp->next;
2091 }
2092#ifdef DEBUG_TREE
2093 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2094 "xmlRemoveProp : attribute not owned by its node\n");
2095#endif
2096 return(-1);
2097}
2098
2099/**
2100 * xmlNewDocPI:
2101 * @doc: the target document
2102 * @name: the processing instruction name
2103 * @content: the PI content
2104 *
2105 * Creation of a processing instruction element.
2106 * Returns a pointer to the new node object.
2107 */
2108xmlNodePtr
2109xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) {
2110 xmlNodePtr cur;
2111
2112 if (name == NULL((void*)0)) {
2113#ifdef DEBUG_TREE
2114 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2115 "xmlNewPI : name == NULL\n");
2116#endif
2117 return(NULL((void*)0));
2118 }
2119
2120 /*
2121 * Allocate a new node and fill the fields.
2122 */
2123 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2124 if (cur == NULL((void*)0)) {
2125 xmlTreeErrMemory("building PI");
2126 return(NULL((void*)0));
2127 }
2128 memset(cur, 0, sizeof(xmlNode));
2129 cur->type = XML_PI_NODE;
2130
2131 if ((doc != NULL((void*)0)) && (doc->dict != NULL((void*)0)))
2132 cur->name = xmlDictLookup(doc->dict, name, -1);
2133 else
2134 cur->name = xmlStrdup(name);
2135 if (content != NULL((void*)0)) {
2136 cur->content = xmlStrdup(content);
2137 }
2138 cur->doc = doc;
2139
2140 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
2141 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))((xmlNodePtr)cur);
2142 return(cur);
2143}
2144
2145/**
2146 * xmlNewPI:
2147 * @name: the processing instruction name
2148 * @content: the PI content
2149 *
2150 * Creation of a processing instruction element.
2151 * Use xmlDocNewPI preferably to get string interning
2152 *
2153 * Returns a pointer to the new node object.
2154 */
2155xmlNodePtr
2156xmlNewPI(const xmlChar *name, const xmlChar *content) {
2157 return(xmlNewDocPI(NULL((void*)0), name, content));
2158}
2159
2160/**
2161 * xmlNewNode:
2162 * @ns: namespace if any
2163 * @name: the node name
2164 *
2165 * Creation of a new node element. @ns is optional (NULL).
2166 *
2167 * Returns a pointer to the new node object. Uses xmlStrdup() to make
2168 * copy of @name.
2169 */
2170xmlNodePtr
2171xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
2172 xmlNodePtr cur;
2173
2174 if (name == NULL((void*)0)) {
2175#ifdef DEBUG_TREE
2176 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2177 "xmlNewNode : name == NULL\n");
2178#endif
2179 return(NULL((void*)0));
2180 }
2181
2182 /*
2183 * Allocate a new node and fill the fields.
2184 */
2185 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2186 if (cur == NULL((void*)0)) {
2187 xmlTreeErrMemory("building node");
2188 return(NULL((void*)0));
2189 }
2190 memset(cur, 0, sizeof(xmlNode));
2191 cur->type = XML_ELEMENT_NODE;
2192
2193 cur->name = xmlStrdup(name);
2194 cur->ns = ns;
2195
2196 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
2197 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))(cur);
2198 return(cur);
2199}
2200
2201/**
2202 * xmlNewNodeEatName:
2203 * @ns: namespace if any
2204 * @name: the node name
2205 *
2206 * Creation of a new node element. @ns is optional (NULL).
2207 *
2208 * Returns a pointer to the new node object, with pointer @name as
2209 * new node's name. Use xmlNewNode() if a copy of @name string is
2210 * is needed as new node's name.
2211 */
2212xmlNodePtr
2213xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) {
2214 xmlNodePtr cur;
2215
2216 if (name == NULL((void*)0)) {
2217#ifdef DEBUG_TREE
2218 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2219 "xmlNewNode : name == NULL\n");
2220#endif
2221 return(NULL((void*)0));
2222 }
2223
2224 /*
2225 * Allocate a new node and fill the fields.
2226 */
2227 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2228 if (cur == NULL((void*)0)) {
2229 xmlTreeErrMemory("building node");
2230 /* we can't check here that name comes from the doc dictionnary */
2231 return(NULL((void*)0));
2232 }
2233 memset(cur, 0, sizeof(xmlNode));
2234 cur->type = XML_ELEMENT_NODE;
2235
2236 cur->name = name;
2237 cur->ns = ns;
2238
2239 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
2240 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))((xmlNodePtr)cur);
2241 return(cur);
2242}
2243
2244/**
2245 * xmlNewDocNode:
2246 * @doc: the document
2247 * @ns: namespace if any
2248 * @name: the node name
2249 * @content: the XML text content if any
2250 *
2251 * Creation of a new node element within a document. @ns and @content
2252 * are optional (NULL).
2253 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2254 * references, but XML special chars need to be escaped first by using
2255 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2256 * need entities support.
2257 *
2258 * Returns a pointer to the new node object.
2259 */
2260xmlNodePtr
2261xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
2262 const xmlChar *name, const xmlChar *content) {
2263 xmlNodePtr cur;
2264
2265 if ((doc != NULL((void*)0)) && (doc->dict != NULL((void*)0)))
2266 cur = xmlNewNodeEatName(ns, (xmlChar *)
2267 xmlDictLookup(doc->dict, name, -1));
2268 else
2269 cur = xmlNewNode(ns, name);
2270 if (cur != NULL((void*)0)) {
2271 cur->doc = doc;
2272 if (content != NULL((void*)0)) {
2273 cur->children = xmlStringGetNodeList(doc, content);
2274 UPDATE_LAST_CHILD_AND_PARENT(cur)if ((cur) != ((void*)0)) { xmlNodePtr ulccur = (cur)->children
; if (ulccur == ((void*)0)) { (cur)->last = ((void*)0); } else
{ while (ulccur->next != ((void*)0)) { ulccur->parent =
(cur); ulccur = ulccur->next; } ulccur->parent = (cur)
; (cur)->last = ulccur; }}
2275 }
2276 }
2277
2278 return(cur);
2279}
2280
2281/**
2282 * xmlNewDocNodeEatName:
2283 * @doc: the document
2284 * @ns: namespace if any
2285 * @name: the node name
2286 * @content: the XML text content if any
2287 *
2288 * Creation of a new node element within a document. @ns and @content
2289 * are optional (NULL).
2290 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2291 * references, but XML special chars need to be escaped first by using
2292 * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2293 * need entities support.
2294 *
2295 * Returns a pointer to the new node object.
2296 */
2297xmlNodePtr
2298xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns,
2299 xmlChar *name, const xmlChar *content) {
2300 xmlNodePtr cur;
2301
2302 cur = xmlNewNodeEatName(ns, name);
2303 if (cur != NULL((void*)0)) {
2304 cur->doc = doc;
2305 if (content != NULL((void*)0)) {
2306 cur->children = xmlStringGetNodeList(doc, content);
2307 UPDATE_LAST_CHILD_AND_PARENT(cur)if ((cur) != ((void*)0)) { xmlNodePtr ulccur = (cur)->children
; if (ulccur == ((void*)0)) { (cur)->last = ((void*)0); } else
{ while (ulccur->next != ((void*)0)) { ulccur->parent =
(cur); ulccur = ulccur->next; } ulccur->parent = (cur)
; (cur)->last = ulccur; }}
2308 }
2309 } else {
2310 /* if name don't come from the doc dictionnary free it here */
2311 if ((name != NULL((void*)0)) && (doc != NULL((void*)0)) &&
2312 (!(xmlDictOwns(doc->dict, name))))
2313 xmlFree(name);
2314 }
2315 return(cur);
2316}
2317
2318#ifdef LIBXML_TREE_ENABLED
2319/**
2320 * xmlNewDocRawNode:
2321 * @doc: the document
2322 * @ns: namespace if any
2323 * @name: the node name
2324 * @content: the text content if any
2325 *
2326 * Creation of a new node element within a document. @ns and @content
2327 * are optional (NULL).
2328 *
2329 * Returns a pointer to the new node object.
2330 */
2331xmlNodePtr
2332xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
2333 const xmlChar *name, const xmlChar *content) {
2334 xmlNodePtr cur;
2335
2336 cur = xmlNewDocNode(doc, ns, name, NULL((void*)0));
2337 if (cur != NULL((void*)0)) {
2338 cur->doc = doc;
2339 if (content != NULL((void*)0)) {
2340 cur->children = xmlNewDocText(doc, content);
2341 UPDATE_LAST_CHILD_AND_PARENT(cur)if ((cur) != ((void*)0)) { xmlNodePtr ulccur = (cur)->children
; if (ulccur == ((void*)0)) { (cur)->last = ((void*)0); } else
{ while (ulccur->next != ((void*)0)) { ulccur->parent =
(cur); ulccur = ulccur->next; } ulccur->parent = (cur)
; (cur)->last = ulccur; }}
2342 }
2343 }
2344 return(cur);
2345}
2346
2347/**
2348 * xmlNewDocFragment:
2349 * @doc: the document owning the fragment
2350 *
2351 * Creation of a new Fragment node.
2352 * Returns a pointer to the new node object.
2353 */
2354xmlNodePtr
2355xmlNewDocFragment(xmlDocPtr doc) {
2356 xmlNodePtr cur;
2357
2358 /*
2359 * Allocate a new DocumentFragment node and fill the fields.
2360 */
2361 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2362 if (cur == NULL((void*)0)) {
2363 xmlTreeErrMemory("building fragment");
2364 return(NULL((void*)0));
2365 }
2366 memset(cur, 0, sizeof(xmlNode));
2367 cur->type = XML_DOCUMENT_FRAG_NODE;
2368
2369 cur->doc = doc;
2370
2371 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
2372 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))(cur);
2373 return(cur);
2374}
2375#endif /* LIBXML_TREE_ENABLED */
2376
2377/**
2378 * xmlNewText:
2379 * @content: the text content
2380 *
2381 * Creation of a new text node.
2382 * Returns a pointer to the new node object.
2383 */
2384xmlNodePtr
2385xmlNewText(const xmlChar *content) {
2386 xmlNodePtr cur;
2387
2388 /*
2389 * Allocate a new node and fill the fields.
2390 */
2391 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2392 if (cur == NULL((void*)0)) {
2393 xmlTreeErrMemory("building text");
2394 return(NULL((void*)0));
2395 }
2396 memset(cur, 0, sizeof(xmlNode));
2397 cur->type = XML_TEXT_NODE;
2398
2399 cur->name = xmlStringText;
2400 if (content != NULL((void*)0)) {
2401 cur->content = xmlStrdup(content);
2402 }
2403
2404 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
2405 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))(cur);
2406 return(cur);
2407}
2408
2409#ifdef LIBXML_TREE_ENABLED
2410/**
2411 * xmlNewTextChild:
2412 * @parent: the parent node
2413 * @ns: a namespace if any
2414 * @name: the name of the child
2415 * @content: the text content of the child if any.
2416 *
2417 * Creation of a new child element, added at the end of @parent children list.
2418 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2419 * created element inherits the namespace of @parent. If @content is non NULL,
2420 * a child TEXT node will be created containing the string @content.
2421 * NOTE: Use xmlNewChild() if @content will contain entities that need to be
2422 * preserved. Use this function, xmlNewTextChild(), if you need to ensure that
2423 * reserved XML chars that might appear in @content, such as the ampersand,
2424 * greater-than or less-than signs, are automatically replaced by their XML
2425 * escaped entity representations.
2426 *
2427 * Returns a pointer to the new node object.
2428 */
2429xmlNodePtr
2430xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
2431 const xmlChar *name, const xmlChar *content) {
2432 xmlNodePtr cur, prev;
2433
2434 if (parent == NULL((void*)0)) {
2435#ifdef DEBUG_TREE
2436 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2437 "xmlNewTextChild : parent == NULL\n");
2438#endif
2439 return(NULL((void*)0));
2440 }
2441
2442 if (name == NULL((void*)0)) {
2443#ifdef DEBUG_TREE
2444 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2445 "xmlNewTextChild : name == NULL\n");
2446#endif
2447 return(NULL((void*)0));
2448 }
2449
2450 /*
2451 * Allocate a new node
2452 */
2453 if (parent->type == XML_ELEMENT_NODE) {
2454 if (ns == NULL((void*)0))
2455 cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
2456 else
2457 cur = xmlNewDocRawNode(parent->doc, ns, name, content);
2458 } else if ((parent->type == XML_DOCUMENT_NODE) ||
2459 (parent->type == XML_HTML_DOCUMENT_NODE)) {
2460 if (ns == NULL((void*)0))
2461 cur = xmlNewDocRawNode((xmlDocPtr) parent, NULL((void*)0), name, content);
2462 else
2463 cur = xmlNewDocRawNode((xmlDocPtr) parent, ns, name, content);
2464 } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
2465 cur = xmlNewDocRawNode( parent->doc, ns, name, content);
2466 } else {
2467 return(NULL((void*)0));
2468 }
2469 if (cur == NULL((void*)0)) return(NULL((void*)0));
2470
2471 /*
2472 * add the new element at the end of the children list.
2473 */
2474 cur->type = XML_ELEMENT_NODE;
2475 cur->parent = parent;
2476 cur->doc = parent->doc;
2477 if (parent->children == NULL((void*)0)) {
2478 parent->children = cur;
2479 parent->last = cur;
2480 } else {
2481 prev = parent->last;
2482 prev->next = cur;
2483 cur->prev = prev;
2484 parent->last = cur;
2485 }
2486
2487 return(cur);
2488}
2489#endif /* LIBXML_TREE_ENABLED */
2490
2491/**
2492 * xmlNewCharRef:
2493 * @doc: the document
2494 * @name: the char ref string, starting with # or "&# ... ;"
2495 *
2496 * Creation of a new character reference node.
2497 * Returns a pointer to the new node object.
2498 */
2499xmlNodePtr
2500xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
2501 xmlNodePtr cur;
2502
2503 if (name == NULL((void*)0))
2504 return(NULL((void*)0));
2505
2506 /*
2507 * Allocate a new node and fill the fields.
2508 */
2509 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2510 if (cur == NULL((void*)0)) {
2511 xmlTreeErrMemory("building character reference");
2512 return(NULL((void*)0));
2513 }
2514 memset(cur, 0, sizeof(xmlNode));
2515 cur->type = XML_ENTITY_REF_NODE;
2516
2517 cur->doc = doc;
2518 if (name[0] == '&') {
2519 int len;
2520 name++;
2521 len = xmlStrlen(name);
2522 if (name[len - 1] == ';')
2523 cur->name = xmlStrndup(name, len - 1);
2524 else
2525 cur->name = xmlStrndup(name, len);
2526 } else
2527 cur->name = xmlStrdup(name);
2528
2529 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
2530 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))(cur);
2531 return(cur);
2532}
2533
2534/**
2535 * xmlNewReference:
2536 * @doc: the document
2537 * @name: the reference name, or the reference string with & and ;
2538 *
2539 * Creation of a new reference node.
2540 * Returns a pointer to the new node object.
2541 */
2542xmlNodePtr
2543xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
2544 xmlNodePtr cur;
2545 xmlEntityPtr ent;
2546
2547 if (name == NULL((void*)0))
2548 return(NULL((void*)0));
2549
2550 /*
2551 * Allocate a new node and fill the fields.
2552 */
2553 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2554 if (cur == NULL((void*)0)) {
2555 xmlTreeErrMemory("building reference");
2556 return(NULL((void*)0));
2557 }
2558 memset(cur, 0, sizeof(xmlNode));
2559 cur->type = XML_ENTITY_REF_NODE;
2560
2561 cur->doc = doc;
2562 if (name[0] == '&') {
2563 int len;
2564 name++;
2565 len = xmlStrlen(name);
2566 if (name[len - 1] == ';')
2567 cur->name = xmlStrndup(name, len - 1);
2568 else
2569 cur->name = xmlStrndup(name, len);
2570 } else
2571 cur->name = xmlStrdup(name);
2572
2573 ent = xmlGetDocEntity(doc, cur->name);
2574 if (ent != NULL((void*)0)) {
2575 cur->content = ent->content;
2576 /*
2577 * The parent pointer in entity is a DTD pointer and thus is NOT
2578 * updated. Not sure if this is 100% correct.
2579 * -George
2580 */
2581 cur->children = (xmlNodePtr) ent;
2582 cur->last = (xmlNodePtr) ent;
2583 }
2584
2585 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
2586 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))(cur);
2587 return(cur);
2588}
2589
2590/**
2591 * xmlNewDocText:
2592 * @doc: the document
2593 * @content: the text content
2594 *
2595 * Creation of a new text node within a document.
2596 * Returns a pointer to the new node object.
2597 */
2598xmlNodePtr
2599xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
2600 xmlNodePtr cur;
2601
2602 cur = xmlNewText(content);
2603 if (cur != NULL((void*)0)) cur->doc = doc;
2604 return(cur);
2605}
2606
2607/**
2608 * xmlNewTextLen:
2609 * @content: the text content
2610 * @len: the text len.
2611 *
2612 * Creation of a new text node with an extra parameter for the content's length
2613 * Returns a pointer to the new node object.
2614 */
2615xmlNodePtr
2616xmlNewTextLen(const xmlChar *content, int len) {
2617 xmlNodePtr cur;
2618
2619 /*
2620 * Allocate a new node and fill the fields.
2621 */
2622 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2623 if (cur == NULL((void*)0)) {
2624 xmlTreeErrMemory("building text");
2625 return(NULL((void*)0));
2626 }
2627 memset(cur, 0, sizeof(xmlNode));
2628 cur->type = XML_TEXT_NODE;
2629
2630 cur->name = xmlStringText;
2631 if (content != NULL((void*)0)) {
2632 cur->content = xmlStrndup(content, len);
2633 }
2634
2635 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
2636 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))(cur);
2637 return(cur);
2638}
2639
2640/**
2641 * xmlNewDocTextLen:
2642 * @doc: the document
2643 * @content: the text content
2644 * @len: the text len.
2645 *
2646 * Creation of a new text node with an extra content length parameter. The
2647 * text node pertain to a given document.
2648 * Returns a pointer to the new node object.
2649 */
2650xmlNodePtr
2651xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
2652 xmlNodePtr cur;
2653
2654 cur = xmlNewTextLen(content, len);
2655 if (cur != NULL((void*)0)) cur->doc = doc;
2656 return(cur);
2657}
2658
2659/**
2660 * xmlNewComment:
2661 * @content: the comment content
2662 *
2663 * Creation of a new node containing a comment.
2664 * Returns a pointer to the new node object.
2665 */
2666xmlNodePtr
2667xmlNewComment(const xmlChar *content) {
2668 xmlNodePtr cur;
2669
2670 /*
2671 * Allocate a new node and fill the fields.
2672 */
2673 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2674 if (cur == NULL((void*)0)) {
2675 xmlTreeErrMemory("building comment");
2676 return(NULL((void*)0));
2677 }
2678 memset(cur, 0, sizeof(xmlNode));
2679 cur->type = XML_COMMENT_NODE;
2680
2681 cur->name = xmlStringComment;
2682 if (content != NULL((void*)0)) {
2683 cur->content = xmlStrdup(content);
2684 }
2685
2686 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
2687 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))(cur);
2688 return(cur);
2689}
2690
2691/**
2692 * xmlNewCDataBlock:
2693 * @doc: the document
2694 * @content: the CDATA block content content
2695 * @len: the length of the block
2696 *
2697 * Creation of a new node containing a CDATA block.
2698 * Returns a pointer to the new node object.
2699 */
2700xmlNodePtr
2701xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
2702 xmlNodePtr cur;
2703
2704 /*
2705 * Allocate a new node and fill the fields.
2706 */
2707 cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2708 if (cur == NULL((void*)0)) {
2709 xmlTreeErrMemory("building CDATA");
2710 return(NULL((void*)0));
2711 }
2712 memset(cur, 0, sizeof(xmlNode));
2713 cur->type = XML_CDATA_SECTION_NODE;
2714 cur->doc = doc;
2715
2716 if (content != NULL((void*)0)) {
2717 cur->content = xmlStrndup(content, len);
2718 }
2719
2720 if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))))
2721 xmlRegisterNodeDefaultValue(*(__xmlRegisterNodeDefaultValue()))(cur);
2722 return(cur);
2723}
2724
2725/**
2726 * xmlNewDocComment:
2727 * @doc: the document
2728 * @content: the comment content
2729 *
2730 * Creation of a new node containing a comment within a document.
2731 * Returns a pointer to the new node object.
2732 */
2733xmlNodePtr
2734xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
2735 xmlNodePtr cur;
2736
2737 cur = xmlNewComment(content);
2738 if (cur != NULL((void*)0)) cur->doc = doc;
2739 return(cur);
2740}
2741
2742/**
2743 * xmlSetTreeDoc:
2744 * @tree: the top element
2745 * @doc: the document
2746 *
2747 * update all nodes under the tree to point to the right document
2748 */
2749void
2750xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) {
2751 xmlAttrPtr prop;
2752
2753 if (tree == NULL((void*)0))
2754 return;
2755 if (tree->doc != doc) {
2756 if(tree->type == XML_ELEMENT_NODE) {
2757 prop = tree->properties;
2758 while (prop != NULL((void*)0)) {
2759 prop->doc = doc;
2760 xmlSetListDoc(prop->children, doc);
2761 prop = prop->next;
2762 }
2763 }
2764 if (tree->children != NULL((void*)0))
2765 xmlSetListDoc(tree->children, doc);
2766 tree->doc = doc;
2767 }
2768}
2769
2770/**
2771 * xmlSetListDoc:
2772 * @list: the first element
2773 * @doc: the document
2774 *
2775 * update all nodes in the list to point to the right document
2776 */
2777void
2778xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc) {
2779 xmlNodePtr cur;
2780
2781 if (list == NULL((void*)0))
2782 return;
2783 cur = list;
2784 while (cur != NULL((void*)0)) {
2785 if (cur->doc != doc)
2786 xmlSetTreeDoc(cur, doc);
2787 cur = cur->next;
2788 }
2789}
2790
2791#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2792/**
2793 * xmlNewChild:
2794 * @parent: the parent node
2795 * @ns: a namespace if any
2796 * @name: the name of the child
2797 * @content: the XML content of the child if any.
2798 *
2799 * Creation of a new child element, added at the end of @parent children list.
2800 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2801 * created element inherits the namespace of @parent. If @content is non NULL,
2802 * a child list containing the TEXTs and ENTITY_REFs node will be created.
2803 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
2804 * references. XML special chars must be escaped first by using
2805 * xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used.
2806 *
2807 * Returns a pointer to the new node object.
2808 */
2809xmlNodePtr
2810xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
2811 const xmlChar *name, const xmlChar *content) {
2812 xmlNodePtr cur, prev;
2813
2814 if (parent == NULL((void*)0)) {
2815#ifdef DEBUG_TREE
2816 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2817 "xmlNewChild : parent == NULL\n");
2818#endif
2819 return(NULL((void*)0));
2820 }
2821
2822 if (name == NULL((void*)0)) {
2823#ifdef DEBUG_TREE
2824 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2825 "xmlNewChild : name == NULL\n");
2826#endif
2827 return(NULL((void*)0));
2828 }
2829
2830 /*
2831 * Allocate a new node
2832 */
2833 if (parent->type == XML_ELEMENT_NODE) {
2834 if (ns == NULL((void*)0))
2835 cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
2836 else
2837 cur = xmlNewDocNode(parent->doc, ns, name, content);
2838 } else if ((parent->type == XML_DOCUMENT_NODE) ||
2839 (parent->type == XML_HTML_DOCUMENT_NODE)) {
2840 if (ns == NULL((void*)0))
2841 cur = xmlNewDocNode((xmlDocPtr) parent, NULL((void*)0), name, content);
2842 else
2843 cur = xmlNewDocNode((xmlDocPtr) parent, ns, name, content);
2844 } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
2845 cur = xmlNewDocNode( parent->doc, ns, name, content);
2846 } else {
2847 return(NULL((void*)0));
2848 }
2849 if (cur == NULL((void*)0)) return(NULL((void*)0));
2850
2851 /*
2852 * add the new element at the end of the children list.
2853 */
2854 cur->type = XML_ELEMENT_NODE;
2855 cur->parent = parent;
2856 cur->doc = parent->doc;
2857 if (parent->children == NULL((void*)0)) {
2858 parent->children = cur;
2859 parent->last = cur;
2860 } else {
2861 prev = parent->last;
2862 prev->next = cur;
2863 cur->prev = prev;
2864 parent->last = cur;
2865 }
2866
2867 return(cur);
2868}
2869#endif /* LIBXML_TREE_ENABLED */
2870
2871/**
2872 * xmlAddPropSibling:
2873 * @prev: the attribute to which @prop is added after
2874 * @cur: the base attribute passed to calling function
2875 * @prop: the new attribute
2876 *
2877 * Add a new attribute after @prev using @cur as base attribute.
2878 * When inserting before @cur, @prev is passed as @cur->prev.
2879 * When inserting after @cur, @prev is passed as @cur.
2880 * If an existing attribute is found it is detroyed prior to adding @prop.
2881 *
2882 * Returns the attribute being inserted or NULL in case of error.
2883 */
2884static xmlNodePtr
2885xmlAddPropSibling(xmlNodePtr prev, xmlNodePtr cur, xmlNodePtr prop) {
2886 xmlAttrPtr attr;
2887
2888 if (cur->type != XML_ATTRIBUTE_NODE)
2889 return(NULL((void*)0));
2890
2891 /* check if an attribute with the same name exists */
2892 if (prop->ns == NULL((void*)0))
2893 attr = xmlHasNsProp(cur->parent, prop->name, NULL((void*)0));
2894 else
2895 attr = xmlHasNsProp(cur->parent, prop->name, prop->ns->href);
2896
2897 if (prop->doc != cur->doc) {
2898 xmlSetTreeDoc(prop, cur->doc);
2899 }
2900 prop->parent = cur->parent;
2901 prop->prev = prev;
2902 if (prev != NULL((void*)0)) {
2903 prop->next = prev->next;
2904 prev->next = prop;
2905 if (prop->next)
2906 prop->next->prev = prop;
2907 } else {
2908 prop->next = cur;
2909 cur->prev = prop;
2910 }
2911 if (prop->prev == NULL((void*)0) && prop->parent != NULL((void*)0))
2912 prop->parent->properties = (xmlAttrPtr) prop;
2913 if ((attr != NULL((void*)0)) && (attr->type != XML_ATTRIBUTE_DECL)) {
2914 /* different instance, destroy it (attributes must be unique) */
2915 xmlRemoveProp((xmlAttrPtr) attr);
2916 }
2917 return prop;
2918}
2919
2920/**
2921 * xmlAddNextSibling:
2922 * @cur: the child node
2923 * @elem: the new node
2924 *
2925 * Add a new node @elem as the next sibling of @cur
2926 * If the new node was already inserted in a document it is
2927 * first unlinked from its existing context.
2928 * As a result of text merging @elem may be freed.
2929 * If the new node is ATTRIBUTE, it is added into properties instead of children.
2930 * If there is an attribute with equal name, it is first destroyed.
2931 *
2932 * Returns the new node or NULL in case of error.
2933 */
2934xmlNodePtr
2935xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
2936 if (cur == NULL((void*)0)) {
2937#ifdef DEBUG_TREE
2938 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2939 "xmlAddNextSibling : cur == NULL\n");
2940#endif
2941 return(NULL((void*)0));
2942 }
2943 if (elem == NULL((void*)0)) {
2944#ifdef DEBUG_TREE
2945 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2946 "xmlAddNextSibling : elem == NULL\n");
2947#endif
2948 return(NULL((void*)0));
2949 }
2950
2951 if (cur == elem) {
2952#ifdef DEBUG_TREE
2953 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
2954 "xmlAddNextSibling : cur == elem\n");
2955#endif
2956 return(NULL((void*)0));
2957 }
2958
2959 xmlUnlinkNode(elem);
2960
2961 if (elem->type == XML_TEXT_NODE) {
2962 if (cur->type == XML_TEXT_NODE) {
2963 xmlNodeAddContent(cur, elem->content);
2964 xmlFreeNode(elem);
2965 return(cur);
2966 }
2967 if ((cur->next != NULL((void*)0)) && (cur->next->type == XML_TEXT_NODE) &&
2968 (cur->name == cur->next->name)) {
2969 xmlChar *tmp;
2970
2971 tmp = xmlStrdup(elem->content);
2972 tmp = xmlStrcat(tmp, cur->next->content);
2973 xmlNodeSetContent(cur->next, tmp);
2974 xmlFree(tmp);
2975 xmlFreeNode(elem);
2976 return(cur->next);
2977 }
2978 } else if (elem->type == XML_ATTRIBUTE_NODE) {
2979 return xmlAddPropSibling(cur, cur, elem);
2980 }
2981
2982 if (elem->doc != cur->doc) {
2983 xmlSetTreeDoc(elem, cur->doc);
2984 }
2985 elem->parent = cur->parent;
2986 elem->prev = cur;
2987 elem->next = cur->next;
2988 cur->next = elem;
2989 if (elem->next != NULL((void*)0))
2990 elem->next->prev = elem;
2991 if ((elem->parent != NULL((void*)0)) && (elem->parent->last == cur))
2992 elem->parent->last = elem;
2993 return(elem);
2994}
2995
2996#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
2997 defined(LIBXML_SCHEMAS_ENABLED)
2998/**
2999 * xmlAddPrevSibling:
3000 * @cur: the child node
3001 * @elem: the new node
3002 *
3003 * Add a new node @elem as the previous sibling of @cur
3004 * merging adjacent TEXT nodes (@elem may be freed)
3005 * If the new node was already inserted in a document it is
3006 * first unlinked from its existing context.
3007 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3008 * If there is an attribute with equal name, it is first destroyed.
3009 *
3010 * Returns the new node or NULL in case of error.
3011 */
3012xmlNodePtr
3013xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
3014 if (cur == NULL((void*)0)) {
3015#ifdef DEBUG_TREE
3016 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3017 "xmlAddPrevSibling : cur == NULL\n");
3018#endif
3019 return(NULL((void*)0));
3020 }
3021 if (elem == NULL((void*)0)) {
3022#ifdef DEBUG_TREE
3023 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3024 "xmlAddPrevSibling : elem == NULL\n");
3025#endif
3026 return(NULL((void*)0));
3027 }
3028
3029 if (cur == elem) {
3030#ifdef DEBUG_TREE
3031 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3032 "xmlAddPrevSibling : cur == elem\n");
3033#endif
3034 return(NULL((void*)0));
3035 }
3036
3037 xmlUnlinkNode(elem);
3038
3039 if (elem->type == XML_TEXT_NODE) {
3040 if (cur->type == XML_TEXT_NODE) {
3041 xmlChar *tmp;
3042
3043 tmp = xmlStrdup(elem->content);
3044 tmp = xmlStrcat(tmp, cur->content);
3045 xmlNodeSetContent(cur, tmp);
3046 xmlFree(tmp);
3047 xmlFreeNode(elem);
3048 return(cur);
3049 }
3050 if ((cur->prev != NULL((void*)0)) && (cur->prev->type == XML_TEXT_NODE) &&
3051 (cur->name == cur->prev->name)) {
3052 xmlNodeAddContent(cur->prev, elem->content);
3053 xmlFreeNode(elem);
3054 return(cur->prev);
3055 }
3056 } else if (elem->type == XML_ATTRIBUTE_NODE) {
3057 return xmlAddPropSibling(cur->prev, cur, elem);
3058 }
3059
3060 if (elem->doc != cur->doc) {
3061 xmlSetTreeDoc(elem, cur->doc);
3062 }
3063 elem->parent = cur->parent;
3064 elem->next = cur;
3065 elem->prev = cur->prev;
3066 cur->prev = elem;
3067 if (elem->prev != NULL((void*)0))
3068 elem->prev->next = elem;
3069 if ((elem->parent != NULL((void*)0)) && (elem->parent->children == cur)) {
3070 elem->parent->children = elem;
3071 }
3072 return(elem);
3073}
3074#endif /* LIBXML_TREE_ENABLED */
3075
3076/**
3077 * xmlAddSibling:
3078 * @cur: the child node
3079 * @elem: the new node
3080 *
3081 * Add a new element @elem to the list of siblings of @cur
3082 * merging adjacent TEXT nodes (@elem may be freed)
3083 * If the new element was already inserted in a document it is
3084 * first unlinked from its existing context.
3085 *
3086 * Returns the new element or NULL in case of error.
3087 */
3088xmlNodePtr
3089xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
3090 xmlNodePtr parent;
3091
3092 if (cur == NULL((void*)0)) {
3093#ifdef DEBUG_TREE
3094 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3095 "xmlAddSibling : cur == NULL\n");
3096#endif
3097 return(NULL((void*)0));
3098 }
3099
3100 if (elem == NULL((void*)0)) {
3101#ifdef DEBUG_TREE
3102 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3103 "xmlAddSibling : elem == NULL\n");
3104#endif
3105 return(NULL((void*)0));
3106 }
3107
3108 if (cur == elem) {
3109#ifdef DEBUG_TREE
3110 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3111 "xmlAddSibling : cur == elem\n");
3112#endif
3113 return(NULL((void*)0));
3114 }
3115
3116 /*
3117 * Constant time is we can rely on the ->parent->last to find
3118 * the last sibling.
3119 */
3120 if ((cur->type != XML_ATTRIBUTE_NODE) && (cur->parent != NULL((void*)0)) &&
3121 (cur->parent->children != NULL((void*)0)) &&
3122 (cur->parent->last != NULL((void*)0)) &&
3123 (cur->parent->last->next == NULL((void*)0))) {
3124 cur = cur->parent->last;
3125 } else {
3126 while (cur->next != NULL((void*)0)) cur = cur->next;
3127 }
3128
3129 xmlUnlinkNode(elem);
3130
3131 if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE) &&
3132 (cur->name == elem->name)) {
3133 xmlNodeAddContent(cur, elem->content);
3134 xmlFreeNode(elem);
3135 return(cur);
3136 } else if (elem->type == XML_ATTRIBUTE_NODE) {
3137 return xmlAddPropSibling(cur, cur, elem);
3138 }
3139
3140 if (elem->doc != cur->doc) {
3141 xmlSetTreeDoc(elem, cur->doc);
3142 }
3143 parent = cur->parent;
3144 elem->prev = cur;
3145 elem->next = NULL((void*)0);
3146 elem->parent = parent;
3147 cur->next = elem;
3148 if (parent != NULL((void*)0))
3149 parent->last = elem;
3150
3151 return(elem);
3152}
3153
3154/**
3155 * xmlAddChildList:
3156 * @parent: the parent node
3157 * @cur: the first node in the list
3158 *
3159 * Add a list of node at the end of the child list of the parent
3160 * merging adjacent TEXT nodes (@cur may be freed)
3161 *
3162 * Returns the last child or NULL in case of error.
3163 */
3164xmlNodePtr
3165xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
3166 xmlNodePtr prev;
3167
3168 if (parent == NULL((void*)0)) {
3169#ifdef DEBUG_TREE
3170 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3171 "xmlAddChildList : parent == NULL\n");
3172#endif
3173 return(NULL((void*)0));
3174 }
3175
3176 if (cur == NULL((void*)0)) {
3177#ifdef DEBUG_TREE
3178 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3179 "xmlAddChildList : child == NULL\n");
3180#endif
3181 return(NULL((void*)0));
3182 }
3183
3184 if ((cur->doc != NULL((void*)0)) && (parent->doc != NULL((void*)0)) &&
3185 (cur->doc != parent->doc)) {
3186#ifdef DEBUG_TREE
3187 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3188 "Elements moved to a different document\n");
3189#endif
3190 }
3191
3192 /*
3193 * add the first element at the end of the children list.
3194 */
3195
3196 if (parent->children == NULL((void*)0)) {
3197 parent->children = cur;
3198 } else {
3199 /*
3200 * If cur and parent->last both are TEXT nodes, then merge them.
3201 */
3202 if ((cur->type == XML_TEXT_NODE) &&
3203 (parent->last->type == XML_TEXT_NODE) &&
3204 (cur->name == parent->last->name)) {
3205 xmlNodeAddContent(parent->last, cur->content);
3206 /*
3207 * if it's the only child, nothing more to be done.
3208 */
3209 if (cur->next == NULL((void*)0)) {
3210 xmlFreeNode(cur);
3211 return(parent->last);
3212 }
3213 prev = cur;
3214 cur = cur->next;
3215 xmlFreeNode(prev);
3216 }
3217 prev = parent->last;
3218 prev->next = cur;
3219 cur->prev = prev;
3220 }
3221 while (cur->next != NULL((void*)0)) {
3222 cur->parent = parent;
3223 if (cur->doc != parent->doc) {
3224 xmlSetTreeDoc(cur, parent->doc);
3225 }
3226 cur = cur->next;
3227 }
3228 cur->parent = parent;
3229 /* the parent may not be linked to a doc ! */
3230 if (cur->doc != parent->doc) {
3231 xmlSetTreeDoc(cur, parent->doc);
3232 }
3233 parent->last = cur;
3234
3235 return(cur);
3236}
3237
3238/**
3239 * xmlAddChild:
3240 * @parent: the parent node
3241 * @cur: the child node
3242 *
3243 * Add a new node to @parent, at the end of the child (or property) list
3244 * merging adjacent TEXT nodes (in which case @cur is freed)
3245 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3246 * If there is an attribute with equal name, it is first destroyed.
3247 *
3248 * Returns the child or NULL in case of error.
3249 */
3250xmlNodePtr
3251xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
3252 xmlNodePtr prev;
3253
3254 if (parent == NULL((void*)0)) {
3255#ifdef DEBUG_TREE
3256 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3257 "xmlAddChild : parent == NULL\n");
3258#endif
3259 return(NULL((void*)0));
3260 }
3261
3262 if (cur == NULL((void*)0)) {
3263#ifdef DEBUG_TREE
3264 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3265 "xmlAddChild : child == NULL\n");
3266#endif
3267 return(NULL((void*)0));
3268 }
3269
3270 if (parent == cur) {
3271#ifdef DEBUG_TREE
3272 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3273 "xmlAddChild : parent == cur\n");
3274#endif
3275 return(NULL((void*)0));
3276 }
3277 /*
3278 * If cur is a TEXT node, merge its content with adjacent TEXT nodes
3279 * cur is then freed.
3280 */
3281 if (cur->type == XML_TEXT_NODE) {
3282 if ((parent->type == XML_TEXT_NODE) &&
3283 (parent->content != NULL((void*)0)) &&
3284 (parent->name == cur->name)) {
3285 xmlNodeAddContent(parent, cur->content);
3286 xmlFreeNode(cur);
3287 return(parent);
3288 }
3289 if ((parent->last != NULL((void*)0)) && (parent->last->type == XML_TEXT_NODE) &&
3290 (parent->last->name == cur->name) &&
3291 (parent->last != cur)) {
3292 xmlNodeAddContent(parent->last, cur->content);
3293 xmlFreeNode(cur);
3294 return(parent->last);
3295 }
3296 }
3297
3298 /*
3299 * add the new element at the end of the children list.
3300 */
3301 prev = cur->parent;
3302 cur->parent = parent;
3303 if (cur->doc != parent->doc) {
3304 xmlSetTreeDoc(cur, parent->doc);
3305 }
3306 /* this check prevents a loop on tree-traversions if a developer
3307 * tries to add a node to its parent multiple times
3308 */
3309 if (prev == parent)
3310 return(cur);
3311
3312 /*
3313 * Coalescing
3314 */
3315 if ((parent->type == XML_TEXT_NODE) &&
3316 (parent->content != NULL((void*)0)) &&
3317 (parent != cur)) {
3318 xmlNodeAddContent(parent, cur->content);
3319 xmlFreeNode(cur);
3320 return(parent);
3321 }
3322 if (cur->type == XML_ATTRIBUTE_NODE) {
3323 if (parent->type != XML_ELEMENT_NODE)
3324 return(NULL((void*)0));
3325 if (parent->properties != NULL((void*)0)) {
3326 /* check if an attribute with the same name exists */
3327 xmlAttrPtr lastattr;
3328
3329 if (cur->ns == NULL((void*)0))
3330 lastattr = xmlHasNsProp(parent, cur->name, NULL((void*)0));
3331 else
3332 lastattr = xmlHasNsProp(parent, cur->name, cur->ns->href);
3333 if ((lastattr != NULL((void*)0)) && (lastattr != (xmlAttrPtr) cur) && (lastattr->type != XML_ATTRIBUTE_DECL)) {
3334 /* different instance, destroy it (attributes must be unique) */
3335 xmlUnlinkNode((xmlNodePtr) lastattr);
3336 xmlFreeProp(lastattr);
3337 }
3338 if (lastattr == (xmlAttrPtr) cur)
3339 return(cur);
3340
3341 }
3342 if (parent->properties == NULL((void*)0)) {
3343 parent->properties = (xmlAttrPtr) cur;
3344 } else {
3345 /* find the end */
3346 xmlAttrPtr lastattr = parent->properties;
3347 while (lastattr->next != NULL((void*)0)) {
3348 lastattr = lastattr->next;
3349 }
3350 lastattr->next = (xmlAttrPtr) cur;
3351 ((xmlAttrPtr) cur)->prev = lastattr;
3352 }
3353 } else {
3354 if (parent->children == NULL((void*)0)) {
3355 parent->children = cur;
3356 parent->last = cur;
3357 } else {
3358 prev = parent->last;
3359 prev->next = cur;
3360 cur->prev = prev;
3361 parent->last = cur;
3362 }
3363 }
3364 return(cur);
3365}
3366
3367/**
3368 * xmlGetLastChild:
3369 * @parent: the parent node
3370 *
3371 * Search the last child of a node.
3372 * Returns the last child or NULL if none.
3373 */
3374xmlNodePtr
3375xmlGetLastChild(xmlNodePtr parent) {
3376 if (parent == NULL((void*)0)) {
3377#ifdef DEBUG_TREE
3378 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3379 "xmlGetLastChild : parent == NULL\n");
3380#endif
3381 return(NULL((void*)0));
3382 }
3383 return(parent->last);
3384}
3385
3386#ifdef LIBXML_TREE_ENABLED
3387/*
3388 * 5 interfaces from DOM ElementTraversal
3389 */
3390
3391/**
3392 * xmlChildElementCount:
3393 * @parent: the parent node
3394 *
3395 * Finds the current number of child nodes of that element which are
3396 * element nodes.
3397 * Note the handling of entities references is different than in
3398 * the W3C DOM element traversal spec since we don't have back reference
3399 * from entities content to entities references.
3400 *
3401 * Returns the count of element child or 0 if not available
3402 */
3403unsigned long
3404xmlChildElementCount(xmlNodePtr parent) {
3405 unsigned long ret = 0;
3406 xmlNodePtr cur = NULL((void*)0);
3407
3408 if (parent == NULL((void*)0))
3409 return(0);
3410 switch (parent->type) {
3411 case XML_ELEMENT_NODE:
3412 case XML_ENTITY_NODE:
3413 case XML_DOCUMENT_NODE:
3414 case XML_HTML_DOCUMENT_NODE:
3415 cur = parent->children;
3416 break;
3417 default:
3418 return(0);
3419 }
3420 while (cur != NULL((void*)0)) {
3421 if (cur->type == XML_ELEMENT_NODE)
3422 ret++;
3423 cur = cur->next;
3424 }
3425 return(ret);
3426}
3427
3428/**
3429 * xmlFirstElementChild:
3430 * @parent: the parent node
3431 *
3432 * Finds the first child node of that element which is a Element node
3433 * Note the handling of entities references is different than in
3434 * the W3C DOM element traversal spec since we don't have back reference
3435 * from entities content to entities references.
3436 *
3437 * Returns the first element child or NULL if not available
3438 */
3439xmlNodePtr
3440xmlFirstElementChild(xmlNodePtr parent) {
3441 xmlNodePtr cur = NULL((void*)0);
3442
3443 if (parent == NULL((void*)0))
3444 return(NULL((void*)0));
3445 switch (parent->type) {
3446 case XML_ELEMENT_NODE:
3447 case XML_ENTITY_NODE:
3448 case XML_DOCUMENT_NODE:
3449 case XML_HTML_DOCUMENT_NODE:
3450 cur = parent->children;
3451 break;
3452 default:
3453 return(NULL((void*)0));
3454 }
3455 while (cur != NULL((void*)0)) {
3456 if (cur->type == XML_ELEMENT_NODE)
3457 return(cur);
3458 cur = cur->next;
3459 }
3460 return(NULL((void*)0));
3461}
3462
3463/**
3464 * xmlLastElementChild:
3465 * @parent: the parent node
3466 *
3467 * Finds the last child node of that element which is a Element node
3468 * Note the handling of entities references is different than in
3469 * the W3C DOM element traversal spec since we don't have back reference
3470 * from entities content to entities references.
3471 *
3472 * Returns the last element child or NULL if not available
3473 */
3474xmlNodePtr
3475xmlLastElementChild(xmlNodePtr parent) {
3476 xmlNodePtr cur = NULL((void*)0);
3477
3478 if (parent == NULL((void*)0))
3479 return(NULL((void*)0));
3480 switch (parent->type) {
3481 case XML_ELEMENT_NODE:
3482 case XML_ENTITY_NODE:
3483 case XML_DOCUMENT_NODE:
3484 case XML_HTML_DOCUMENT_NODE:
3485 cur = parent->last;
3486 break;
3487 default:
3488 return(NULL((void*)0));
3489 }
3490 while (cur != NULL((void*)0)) {
3491 if (cur->type == XML_ELEMENT_NODE)
3492 return(cur);
3493 cur = cur->prev;
3494 }
3495 return(NULL((void*)0));
3496}
3497
3498/**
3499 * xmlPreviousElementSibling:
3500 * @node: the current node
3501 *
3502 * Finds the first closest previous sibling of the node which is an
3503 * element node.
3504 * Note the handling of entities references is different than in
3505 * the W3C DOM element traversal spec since we don't have back reference
3506 * from entities content to entities references.
3507 *
3508 * Returns the previous element sibling or NULL if not available
3509 */
3510xmlNodePtr
3511xmlPreviousElementSibling(xmlNodePtr node) {
3512 if (node == NULL((void*)0))
3513 return(NULL((void*)0));
3514 switch (node->type) {
3515 case XML_ELEMENT_NODE:
3516 case XML_TEXT_NODE:
3517 case XML_CDATA_SECTION_NODE:
3518 case XML_ENTITY_REF_NODE:
3519 case XML_ENTITY_NODE:
3520 case XML_PI_NODE:
3521 case XML_COMMENT_NODE:
3522 case XML_XINCLUDE_START:
3523 case XML_XINCLUDE_END:
3524 node = node->prev;
3525 break;
3526 default:
3527 return(NULL((void*)0));
3528 }
3529 while (node != NULL((void*)0)) {
3530 if (node->type == XML_ELEMENT_NODE)
3531 return(node);
3532 node = node->next;
3533 }
3534 return(NULL((void*)0));
3535}
3536
3537/**
3538 * xmlNextElementSibling:
3539 * @node: the current node
3540 *
3541 * Finds the first closest next sibling of the node which is an
3542 * element node.
3543 * Note the handling of entities references is different than in
3544 * the W3C DOM element traversal spec since we don't have back reference
3545 * from entities content to entities references.
3546 *
3547 * Returns the next element sibling or NULL if not available
3548 */
3549xmlNodePtr
3550xmlNextElementSibling(xmlNodePtr node) {
3551 if (node == NULL((void*)0))
3552 return(NULL((void*)0));
3553 switch (node->type) {
3554 case XML_ELEMENT_NODE:
3555 case XML_TEXT_NODE:
3556 case XML_CDATA_SECTION_NODE:
3557 case XML_ENTITY_REF_NODE:
3558 case XML_ENTITY_NODE:
3559 case XML_PI_NODE:
3560 case XML_COMMENT_NODE:
3561 case XML_DTD_NODE:
3562 case XML_XINCLUDE_START:
3563 case XML_XINCLUDE_END:
3564 node = node->next;
3565 break;
3566 default:
3567 return(NULL((void*)0));
3568 }
3569 while (node != NULL((void*)0)) {
3570 if (node->type == XML_ELEMENT_NODE)
3571 return(node);
3572 node = node->next;
3573 }
3574 return(NULL((void*)0));
3575}
3576
3577#endif /* LIBXML_TREE_ENABLED */
3578
3579/**
3580 * xmlFreeNodeList:
3581 * @cur: the first node in the list
3582 *
3583 * Free a node and all its siblings, this is a recursive behaviour, all
3584 * the children are freed too.
3585 */
3586void
3587xmlFreeNodeList(xmlNodePtr cur) {
3588 xmlNodePtr next;
3589 xmlDictPtr dict = NULL((void*)0);
3590
3591 if (cur == NULL((void*)0)) return;
3592 if (cur->type == XML_NAMESPACE_DECL) {
3593 xmlFreeNsList((xmlNsPtr) cur);
3594 return;
3595 }
3596 if ((cur->type == XML_DOCUMENT_NODE) ||
3597#ifdef LIBXML_DOCB_ENABLED
3598 (cur->type == XML_DOCB_DOCUMENT_NODE) ||
3599#endif
3600 (cur->type == XML_HTML_DOCUMENT_NODE)) {
3601 xmlFreeDoc((xmlDocPtr) cur);
3602 return;
3603 }
3604 if (cur->doc != NULL((void*)0)) dict = cur->doc->dict;
3605 while (cur != NULL((void*)0)) {
3606 next = cur->next;
3607 if (cur->type != XML_DTD_NODE) {
3608
3609 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue(*(__xmlDeregisterNodeDefaultValue()))))
3610 xmlDeregisterNodeDefaultValue(*(__xmlDeregisterNodeDefaultValue()))(cur);
3611
3612 if ((cur->children != NULL((void*)0)) &&
3613 (cur->type != XML_ENTITY_REF_NODE))
3614 xmlFreeNodeList(cur->children);
3615 if (((cur->type == XML_ELEMENT_NODE) ||
3616 (cur->type == XML_XINCLUDE_START) ||
3617 (cur->type == XML_XINCLUDE_END)) &&
3618 (cur->properties != NULL((void*)0)))
3619 xmlFreePropList(cur->properties);
3620 if ((cur->type != XML_ELEMENT_NODE) &&
3621 (cur->type != XML_XINCLUDE_START) &&
3622 (cur->type != XML_XINCLUDE_END) &&
3623 (cur->type != XML_ENTITY_REF_NODE) &&
3624 (cur->content != (xmlChar *) &(cur->properties))) {
3625 DICT_FREE(cur->content)if ((cur->content) && ((!dict) || (xmlDictOwns(dict
, (const xmlChar *)(cur->content)) == 0))) xmlFree((char *
)(cur->content));
3626 }
3627 if (((cur->type == XML_ELEMENT_NODE) ||
3628 (cur->type == XML_XINCLUDE_START) ||
3629 (cur->type == XML_XINCLUDE_END)) &&
3630 (cur->nsDef != NULL((void*)0)))
3631 xmlFreeNsList(cur->nsDef);
3632
3633 /*
3634 * When a node is a text node or a comment, it uses a global static
3635 * variable for the name of the node.
3636 * Otherwise the node name might come from the document's
3637 * dictionnary
3638 */
3639 if ((cur->name != NULL((void*)0)) &&
3640 (cur->type != XML_TEXT_NODE) &&
3641 (cur->type != XML_COMMENT_NODE))
3642 DICT_FREE(cur->name)if ((cur->name) && ((!dict) || (xmlDictOwns(dict, (
const xmlChar *)(cur->name)) == 0))) xmlFree((char *)(cur->
name));
3643 xmlFree(cur);
3644 }
3645 cur = next;
3646 }
3647}
3648
3649/**
3650 * xmlFreeNode:
3651 * @cur: the node
3652 *
3653 * Free a node, this is a recursive behaviour, all the children are freed too.
3654 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
3655 */
3656void
3657xmlFreeNode(xmlNodePtr cur) {
3658 xmlDictPtr dict = NULL((void*)0);
3659
3660 if (cur == NULL((void*)0)) return;
3661
3662 /* use xmlFreeDtd for DTD nodes */
3663 if (cur->type == XML_DTD_NODE) {
3664 xmlFreeDtd((xmlDtdPtr) cur);
3665 return;
3666 }
3667 if (cur->type == XML_NAMESPACE_DECL) {
3668 xmlFreeNs((xmlNsPtr) cur);
3669 return;
3670 }
3671 if (cur->type == XML_ATTRIBUTE_NODE) {
3672 xmlFreeProp((xmlAttrPtr) cur);
3673 return;
3674 }
3675
3676 if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue(*(__xmlDeregisterNodeDefaultValue()))))
3677 xmlDeregisterNodeDefaultValue(*(__xmlDeregisterNodeDefaultValue()))(cur);
3678
3679 if (cur->doc != NULL((void*)0)) dict = cur->doc->dict;
3680
3681 if (cur->type == XML_ENTITY_DECL) {
3682 xmlEntityPtr ent = (xmlEntityPtr) cur;
3683 DICT_FREE(ent->SystemID)if ((ent->SystemID) && ((!dict) || (xmlDictOwns(dict
, (const xmlChar *)(ent->SystemID)) == 0))) xmlFree((char *
)(ent->SystemID));
;
3684 DICT_FREE(ent->ExternalID)if ((ent->ExternalID) && ((!dict) || (xmlDictOwns(
dict, (const xmlChar *)(ent->ExternalID)) == 0))) xmlFree(
(char *)(ent->ExternalID));
;
3685 }
3686 if ((cur->children != NULL((void*)0)) &&
3687 (cur->type != XML_ENTITY_REF_NODE))
3688 xmlFreeNodeList(cur->children);
3689 if (((cur->type == XML_ELEMENT_NODE) ||
3690 (cur->type == XML_XINCLUDE_START) ||
3691 (cur->type == XML_XINCLUDE_END)) &&
3692 (cur->properties != NULL((void*)0)))
3693 xmlFreePropList(cur->properties);
3694 if ((cur->type != XML_ELEMENT_NODE) &&
3695 (cur->content != NULL((void*)0)) &&
3696 (cur->type != XML_ENTITY_REF_NODE) &&
3697 (cur->type != XML_XINCLUDE_END) &&
3698 (cur->type != XML_XINCLUDE_START) &&
3699 (cur->content != (xmlChar *) &(cur->properties))) {
3700 DICT_FREE(cur->content)if ((cur->content) && ((!dict) || (xmlDictOwns(dict
, (const xmlChar *)(cur->content)) == 0))) xmlFree((char *
)(cur->content));
3701 }
3702
3703 /*
3704 * When a node is a text node or a comment, it uses a global static
3705 * variable for the name of the node.
3706 * Otherwise the node name might come from the document's dictionnary
3707 */
3708 if ((cur->name != NULL((void*)0)) &&
3709 (cur->type != XML_TEXT_NODE) &&
3710 (cur->type != XML_COMMENT_NODE))
3711 DICT_FREE(cur->name)if ((cur->name) && ((!dict) || (xmlDictOwns(dict, (
const xmlChar *)(cur->name)) == 0))) xmlFree((char *)(cur->
name));
3712
3713 if (((cur->type == XML_ELEMENT_NODE) ||
3714 (cur->type == XML_XINCLUDE_START) ||
3715 (cur->type == XML_XINCLUDE_END)) &&
3716 (cur->nsDef != NULL((void*)0)))
3717 xmlFreeNsList(cur->nsDef);
3718 xmlFree(cur);
3719}
3720
3721/**
3722 * xmlUnlinkNode:
3723 * @cur: the node
3724 *
3725 * Unlink a node from it's current context, the node is not freed
3726 */
3727void
3728xmlUnlinkNode(xmlNodePtr cur) {
3729 if (cur == NULL((void*)0)) {
3730#ifdef DEBUG_TREE
3731 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3732 "xmlUnlinkNode : node == NULL\n");
3733#endif
3734 return;
3735 }
3736 if (cur->type == XML_DTD_NODE) {
3737 xmlDocPtr doc;
3738 doc = cur->doc;
3739 if (doc != NULL((void*)0)) {
3740 if (doc->intSubset == (xmlDtdPtr) cur)
3741 doc->intSubset = NULL((void*)0);
3742 if (doc->extSubset == (xmlDtdPtr) cur)
3743 doc->extSubset = NULL((void*)0);
3744 }
3745 }
3746 if (cur->type == XML_ENTITY_DECL) {
3747 xmlDocPtr doc;
3748 doc = cur->doc;
3749 if (doc != NULL((void*)0)) {
3750 if (doc->intSubset != NULL((void*)0)) {
3751 if (xmlHashLookup(doc->intSubset->entities, cur->name) == cur)
3752 xmlHashRemoveEntry(doc->intSubset->entities, cur->name,
3753 NULL((void*)0));
3754 if (xmlHashLookup(doc->intSubset->pentities, cur->name) == cur)
3755 xmlHashRemoveEntry(doc->intSubset->pentities, cur->name,
3756 NULL((void*)0));
3757 }
3758 if (doc->extSubset != NULL((void*)0)) {
3759 if (xmlHashLookup(doc->extSubset->entities, cur->name) == cur)
3760 xmlHashRemoveEntry(doc->extSubset->entities, cur->name,
3761 NULL((void*)0));
3762 if (xmlHashLookup(doc->extSubset->pentities, cur->name) == cur)
3763 xmlHashRemoveEntry(doc->extSubset->pentities, cur->name,
3764 NULL((void*)0));
3765 }
3766 }
3767 }
3768 if (cur->parent != NULL((void*)0)) {
3769 xmlNodePtr parent;
3770 parent = cur->parent;
3771 if (cur->type == XML_ATTRIBUTE_NODE) {
3772 if (parent->properties == (xmlAttrPtr) cur)
3773 parent->properties = ((xmlAttrPtr) cur)->next;
3774 } else {
3775 if (parent->children == cur)
3776 parent->children = cur->next;
3777 if (parent->last == cur)
3778 parent->last = cur->prev;
3779 }
3780 cur->parent = NULL((void*)0);
3781 }
3782 if (cur->next != NULL((void*)0))
3783 cur->next->prev = cur->prev;
3784 if (cur->prev != NULL((void*)0))
3785 cur->prev->next = cur->next;
3786 cur->next = cur->prev = NULL((void*)0);
3787}
3788
3789#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
3790/**
3791 * xmlReplaceNode:
3792 * @old: the old node
3793 * @cur: the node
3794 *
3795 * Unlink the old node from its current context, prune the new one
3796 * at the same place. If @cur was already inserted in a document it is
3797 * first unlinked from its existing context.
3798 *
3799 * Returns the @old node
3800 */
3801xmlNodePtr
3802xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
3803 if (old == cur) return(NULL((void*)0));
3804 if ((old == NULL((void*)0)) || (old->parent == NULL((void*)0))) {
3805#ifdef DEBUG_TREE
3806 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3807 "xmlReplaceNode : old == NULL or without parent\n");
3808#endif
3809 return(NULL((void*)0));
3810 }
3811 if (cur == NULL((void*)0)) {
3812 xmlUnlinkNode(old);
3813 return(old);
3814 }
3815 if (cur == old) {
3816 return(old);
3817 }
3818 if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) {
3819#ifdef DEBUG_TREE
3820 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3821 "xmlReplaceNode : Trying to replace attribute node with other node type\n");
3822#endif
3823 return(old);
3824 }
3825 if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) {
3826#ifdef DEBUG_TREE
3827 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3828 "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
3829#endif
3830 return(old);
3831 }
3832 xmlUnlinkNode(cur);
3833 xmlSetTreeDoc(cur, old->doc);
3834 cur->parent = old->parent;
3835 cur->next = old->next;
3836 if (cur->next != NULL((void*)0))
3837 cur->next->prev = cur;
3838 cur->prev = old->prev;
3839 if (cur->prev != NULL((void*)0))
3840 cur->prev->next = cur;
3841 if (cur->parent != NULL((void*)0)) {
3842 if (cur->type == XML_ATTRIBUTE_NODE) {
3843 if (cur->parent->properties == (xmlAttrPtr)old)
3844 cur->parent->properties = ((xmlAttrPtr) cur);
3845 } else {
3846 if (cur->parent->children == old)
3847 cur->parent->children = cur;
3848 if (cur->parent->last == old)
3849 cur->parent->last = cur;
3850 }
3851 }
3852 old->next = old->prev = NULL((void*)0);
3853 old->parent = NULL((void*)0);
3854 return(old);
3855}
3856#endif /* LIBXML_TREE_ENABLED */
3857
3858/************************************************************************
3859 * *
3860 * Copy operations *
3861 * *
3862 ************************************************************************/
3863
3864/**
3865 * xmlCopyNamespace:
3866 * @cur: the namespace
3867 *
3868 * Do a copy of the namespace.
3869 *
3870 * Returns: a new #xmlNsPtr, or NULL in case of error.
3871 */
3872xmlNsPtr
3873xmlCopyNamespace(xmlNsPtr cur) {
3874 xmlNsPtr ret;
3875
3876 if (cur == NULL((void*)0)) return(NULL((void*)0));
3877 switch (cur->type) {
3878 case XML_LOCAL_NAMESPACEXML_NAMESPACE_DECL:
3879 ret = xmlNewNs(NULL((void*)0), cur->href, cur->prefix);
3880 break;
3881 default:
3882#ifdef DEBUG_TREE
3883 xmlGenericError(*(__xmlGenericError()))(xmlGenericErrorContext(*(__xmlGenericErrorContext())),
3884 "xmlCopyNamespace: invalid type %d\n", cur->type);
3885#endif
3886 return(NULL((void*)0));
3887 }
3888 return(ret);
3889}
3890
3891/**
3892 * xmlCopyNamespaceList:
3893 * @cur: the first namespace
3894 *
3895 * Do a copy of an namespace list.
3896 *
3897 * Returns: a new #xmlNsPtr, or NULL in case of error.
3898 */
3899xmlNsPtr
3900xmlCopyNamespaceList(xmlNsPtr cur) {
3901 xmlNsPtr ret = NULL((void*)0);
3902 xmlNsPtr p = NULL((void*)0),q;
3903
3904 while (cur != NULL((void*)0)) {
3905 q = xmlCopyNamespace(cur);
3906 if (p == NULL((void*)0)) {
3907 ret = p = q;
3908 } else {
3909 p->next = q;
3910 p = q;
3911 }
3912 cur = cur->next;
3913 }
3914 return(ret);
3915}
3916
3917static xmlNodePtr
3918xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
3919
3920static xmlAttrPtr
3921xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
3922 xmlAttrPtr ret;
3923
3924 if (cur == NULL((void*)0)) return(NULL((void*)0));
3925 if (target != NULL((void*)0))
3926 ret = xmlNewDocProp(target->doc, cur->name, NULL((void*)0));
3927 else if (doc != NULL((void*)0))
3928 ret = xmlNewDocProp(doc, cur->name, NULL((void*)0));
3929 else if (cur->parent != NULL((void*)0))
3930 ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL((void*)0));
3931 else if (cur->children != NULL((void*)0))
3932 ret = xmlNewDocProp(cur->children->doc, cur->name, NULL((void*)0));
3933 else
3934 ret = xmlNewDocProp(NULL((void*)0), cur->name, NULL((void*)0));
3935 if (ret == NULL((void*)0)) return(NULL((void*)0));
3936 ret->parent = target;
3937
3938 if ((cur->ns != NULL((void*)0)) && (target != NULL((void*)0))) {
3939 xmlNsPtr ns;
3940
3941 ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
3942 if (ns == NULL((void*)0)) {
3943 /*
3944 * Humm, we are copying an element whose namespace is defined
3945 * out of the new tree scope. Search it in the original tree
3946 * and add it at the top of the new tree
3947 */
3948 ns = xmlSearchNs(cur->doc, cur->parent, cur->ns->prefix);
3949 if (ns != NULL((void*)0)) {
3950 xmlNodePtr root = target;
3951 xmlNodePtr pred = NULL((void*)0);
3952
3953 while (root->parent != NULL((void*)0)) {
3954 pred = root;
3955 root = root->parent;
3956 }
3957 if (root == (xmlNodePtr) target->doc) {
3958 /* correct possibly cycling above the document elt */
3959 root = pred;
3960 }
3961 ret->ns = xmlNewNs(root, ns->href, ns->prefix);
3962 }
3963 } else {
3964 /*
3965 * we have to find something appropriate here since
3966 * we cant be sure, that the namespce we found is identified
3967 * by the prefix
3968 */
3969 if (xmlStrEqual(ns->href, cur->ns->href)) {
3970 /* this is the nice case */
3971 ret->ns = ns;
3972 } else {
3973 /*
3974 * we are in trouble: we need a new reconcilied namespace.
3975 * This is expensive
3976 */
3977 ret->ns = xmlNewReconciliedNs(target->doc, target, cur->ns);
3978 }
3979 }
3980
3981 } else
3982 ret->ns = NULL((void*)0);
3983
3984 if (cur->children != NULL((void*)0)) {
3985 xmlNodePtr tmp;
3986
3987 ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret);
3988 ret->last = NULL((void*)0);
3989 tmp = ret->children;
3990 while (tmp != NULL((void*)0)) {
3991 /* tmp->parent = (xmlNodePtr)ret; */
3992 if (tmp->next == NULL((void*)0))
3993 ret->last = tmp;
3994 tmp = tmp->next;
3995 }
3996 }
3997 /*
3998 * Try to handle IDs
3999 */
4000 if ((target!= NULL((void*)0)) && (cur!= NULL((void*)0)) &&
4001 (target->doc != NULL((void*)0)) && (cur->doc != NULL((void*)0)) &&
4002 (cur->doc->ids != NULL((void*)0)) && (cur->parent != NULL((void*)0))) {
4003 if (xmlIsID(cur->doc, cur->parent, cur)) {
4004 xmlChar *id;
4005
4006 id = xmlNodeListGetString(cur->doc, cur->children, 1);
4007 if (id != NULL((void*)0)) {
4008 xmlAddID(NULL((void*)0), target->doc, id, ret);
4009 xmlFree(id);
4010 }
4011 }
4012 }
4013 return(ret);
4014}
4015
4016/**
4017 * xmlCopyProp:
4018 * @target: the element where the attribute will be grafted
4019 * @cur: the attribute
4020 *
4021 * Do a copy of the attribute.
4022 *
4023 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4024 */
4025xmlAttrPtr
4026xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
4027 return xmlCopyPropInternal(NULL((void*)0), target, cur);
4028}
4029
4030/**
4031 * xmlCopyPropList:
4032 * @target: the element where the attributes will be grafted
4033 * @cur: the first attribute
4034 *
4035 * Do a copy of an attribute list.
4036 *
4037 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4038 */
4039xmlAttrPtr
4040xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
4041 xmlAttrPtr ret = NULL((void*)0);
4042 xmlAttrPtr p = NULL((void*)0),q;
4043
4044 while (cur != NULL((void*)0)) {
4045 q = xmlCopyProp(target, cur);
4046 if (q == NULL((void*)0))
4047 return(NULL((void*)0));
4048 if (p == NULL((void*)0)) {
4049 ret = p = q;
4050 } else {
4051 p->next = q;
4052 q->prev = p;
4053 p = q;
4054 }
4055 cur = cur->next;
4056 }
4057 return(ret);
4058}
4059
4060/*
4061 * NOTE about the CopyNode operations !
4062 *
4063 * They are split into external and internal parts for one
4064 * tricky reason: namespaces. Doing a direct copy of a node
4065 * say RPM:Copyright without changing the namespace pointer to
4066 * something else can produce stale links. One way to do it is
4067 * to keep a reference counter but this doesn't work as soon
4068 * as one move the element or the subtree out of the scope of
4069 * the existing namespace. The actual solution seems to add
4070 * a copy of the namespace at the top of the copied tree if
4071 * not available in the subtree.
4072 * Hence two functions, the public front-end call the inner ones
4073 * The argument "recursive" normally indicates a recursive copy
4074 * of the node with values 0 (no) and 1 (yes). For XInclude,
4075 * however, we allow a value of 2 to indicate copy properties and
4076 * namespace info, but don't recurse on children.
4077 */
4078
4079static xmlNodePtr
4080xmlStaticCopyNode(const xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
4081 int extended) {
4082 xmlNodePtr ret;
4083
4084 if (node == NULL((void*)0)) return(NULL((void*)0));
4085 switch (node->type) {
4086 case XML_TEXT_NODE: