Coverage Report

Created: 2024-02-11 06:23

/src/libprotobuf-mutator/build/examples/libxml2/external.libxml2/src/external.libxml2/tree.c
Line
Count
Source (jump to first uncovered line)
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
/* To avoid EBCDIC trouble when parsing on zOS */
14
#if defined(__MVS__)
15
#pragma convert("ISO8859-1")
16
#endif
17
18
#define IN_LIBXML
19
#include "libxml.h"
20
21
#include <string.h> /* for memset() only ! */
22
#include <stddef.h>
23
#include <limits.h>
24
#include <ctype.h>
25
#include <stdlib.h>
26
27
#ifdef LIBXML_ZLIB_ENABLED
28
#include <zlib.h>
29
#endif
30
31
#include <libxml/tree.h>
32
#include <libxml/xmlmemory.h>
33
#include <libxml/parser.h>
34
#include <libxml/uri.h>
35
#include <libxml/entities.h>
36
#include <libxml/xmlerror.h>
37
#include <libxml/parserInternals.h>
38
#ifdef LIBXML_HTML_ENABLED
39
#include <libxml/HTMLtree.h>
40
#endif
41
#ifdef LIBXML_DEBUG_ENABLED
42
#include <libxml/debugXML.h>
43
#endif
44
45
#include "private/buf.h"
46
#include "private/entities.h"
47
#include "private/error.h"
48
#include "private/tree.h"
49
50
int __xmlRegisterCallbacks = 0;
51
52
/************************************************************************
53
 *                  *
54
 *    Forward declarations          *
55
 *                  *
56
 ************************************************************************/
57
58
static xmlNsPtr
59
xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns);
60
61
static xmlChar* xmlGetPropNodeValueInternal(const xmlAttr *prop);
62
63
/************************************************************************
64
 *                  *
65
 *    A few static variables and macros     *
66
 *                  *
67
 ************************************************************************/
68
/* #undef xmlStringText */
69
const xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
70
/* #undef xmlStringTextNoenc */
71
const xmlChar xmlStringTextNoenc[] =
72
              { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 };
73
/* #undef xmlStringComment */
74
const xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
75
76
static int xmlCompressMode = 0;
77
78
0
#define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) {   \
79
0
    xmlNodePtr ulccur = (n)->children;          \
80
0
    if (ulccur == NULL) {           \
81
0
        (n)->last = NULL;           \
82
0
    } else {               \
83
0
        while (ulccur->next != NULL) {         \
84
0
    ulccur->parent = (n);         \
85
0
    ulccur = ulccur->next;          \
86
0
  }                \
87
0
  ulccur->parent = (n);           \
88
0
  (n)->last = ulccur;           \
89
0
}}
90
91
0
#define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \
92
0
  (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
93
94
/************************************************************************
95
 *                  *
96
 *    Functions to move to entities.c once the    *
97
 *    API freeze is smoothen and they can be made public. *
98
 *                  *
99
 ************************************************************************/
100
#include <libxml/hash.h>
101
102
#ifdef LIBXML_TREE_ENABLED
103
/**
104
 * xmlGetEntityFromDtd:
105
 * @dtd:  A pointer to the DTD to search
106
 * @name:  The entity name
107
 *
108
 * Do an entity lookup in the DTD entity hash table and
109
 * return the corresponding entity, if found.
110
 *
111
 * Returns A pointer to the entity structure or NULL if not found.
112
 */
113
static xmlEntityPtr
114
0
xmlGetEntityFromDtd(const xmlDtd *dtd, const xmlChar *name) {
115
0
    xmlEntitiesTablePtr table;
116
117
0
    if((dtd != NULL) && (dtd->entities != NULL)) {
118
0
  table = (xmlEntitiesTablePtr) dtd->entities;
119
0
  return((xmlEntityPtr) xmlHashLookup(table, name));
120
  /* return(xmlGetEntityFromTable(table, name)); */
121
0
    }
122
0
    return(NULL);
123
0
}
124
/**
125
 * xmlGetParameterEntityFromDtd:
126
 * @dtd:  A pointer to the DTD to search
127
 * @name:  The entity name
128
 *
129
 * Do an entity lookup in the DTD parameter entity hash table and
130
 * return the corresponding entity, if found.
131
 *
132
 * Returns A pointer to the entity structure or NULL if not found.
133
 */
134
static xmlEntityPtr
135
0
xmlGetParameterEntityFromDtd(const xmlDtd *dtd, const xmlChar *name) {
136
0
    xmlEntitiesTablePtr table;
137
138
0
    if ((dtd != NULL) && (dtd->pentities != NULL)) {
139
0
  table = (xmlEntitiesTablePtr) dtd->pentities;
140
0
  return((xmlEntityPtr) xmlHashLookup(table, name));
141
  /* return(xmlGetEntityFromTable(table, name)); */
142
0
    }
143
0
    return(NULL);
144
0
}
145
#endif /* LIBXML_TREE_ENABLED */
146
147
/************************************************************************
148
 *                  *
149
 *      QName handling helper       *
150
 *                  *
151
 ************************************************************************/
152
153
/**
154
 * xmlBuildQName:
155
 * @ncname:  the Name
156
 * @prefix:  the prefix
157
 * @memory:  preallocated memory
158
 * @len:  preallocated memory length
159
 *
160
 * Builds the QName @prefix:@ncname in @memory if there is enough space
161
 * and prefix is not NULL nor empty, otherwise allocate a new string.
162
 * If prefix is NULL or empty it returns ncname.
163
 *
164
 * Returns the new string which must be freed by the caller if different from
165
 *         @memory and @ncname or NULL in case of error
166
 */
167
xmlChar *
168
xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix,
169
32.7k
        xmlChar *memory, int len) {
170
32.7k
    int lenn, lenp;
171
32.7k
    xmlChar *ret;
172
173
32.7k
    if (ncname == NULL) return(NULL);
174
32.7k
    if (prefix == NULL) return((xmlChar *) ncname);
175
176
7.66k
    lenn = strlen((char *) ncname);
177
7.66k
    lenp = strlen((char *) prefix);
178
179
7.66k
    if ((memory == NULL) || (len < lenn + lenp + 2)) {
180
1.31k
  ret = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
181
1.31k
  if (ret == NULL)
182
0
      return(NULL);
183
6.34k
    } else {
184
6.34k
  ret = memory;
185
6.34k
    }
186
7.66k
    memcpy(&ret[0], prefix, lenp);
187
7.66k
    ret[lenp] = ':';
188
7.66k
    memcpy(&ret[lenp + 1], ncname, lenn);
189
7.66k
    ret[lenn + lenp + 1] = 0;
190
7.66k
    return(ret);
191
7.66k
}
192
193
/**
194
 * xmlSplitQName2:
195
 * @name:  the full QName
196
 * @prefix:  a xmlChar **
197
 *
198
 * DEPRECATED: This function doesn't report malloc failures.
199
 *
200
 * parse an XML qualified name string
201
 *
202
 * [NS 5] QName ::= (Prefix ':')? LocalPart
203
 *
204
 * [NS 6] Prefix ::= NCName
205
 *
206
 * [NS 7] LocalPart ::= NCName
207
 *
208
 * Returns NULL if the name doesn't have a prefix. Otherwise, returns the
209
 * local part, and prefix is updated to get the Prefix. Both the return value
210
 * and the prefix must be freed by the caller.
211
 */
212
xmlChar *
213
0
xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
214
0
    int len = 0;
215
0
    xmlChar *ret = NULL;
216
217
0
    if (prefix == NULL) return(NULL);
218
0
    *prefix = NULL;
219
0
    if (name == NULL) return(NULL);
220
221
#ifndef XML_XML_NAMESPACE
222
    /* xml: prefix is not really a namespace */
223
    if ((name[0] == 'x') && (name[1] == 'm') &&
224
        (name[2] == 'l') && (name[3] == ':'))
225
  return(NULL);
226
#endif
227
228
    /* nasty but valid */
229
0
    if (name[0] == ':')
230
0
  return(NULL);
231
232
    /*
233
     * we are not trying to validate but just to cut, and yes it will
234
     * work even if this is as set of UTF-8 encoded chars
235
     */
236
0
    while ((name[len] != 0) && (name[len] != ':'))
237
0
  len++;
238
239
0
    if (name[len] == 0)
240
0
  return(NULL);
241
242
0
    *prefix = xmlStrndup(name, len);
243
0
    if (*prefix == NULL)
244
0
  return(NULL);
245
0
    ret = xmlStrdup(&name[len + 1]);
246
0
    if (ret == NULL) {
247
0
  if (*prefix != NULL) {
248
0
      xmlFree(*prefix);
249
0
      *prefix = NULL;
250
0
  }
251
0
  return(NULL);
252
0
    }
253
254
0
    return(ret);
255
0
}
256
257
/**
258
 * xmlSplitQName3:
259
 * @name:  the full QName
260
 * @len: an int *
261
 *
262
 * parse an XML qualified name string,i
263
 *
264
 * returns NULL if it is not a Qualified Name, otherwise, update len
265
 *         with the length in byte of the prefix and return a pointer
266
 *         to the start of the name without the prefix
267
 */
268
269
const xmlChar *
270
28.5k
xmlSplitQName3(const xmlChar *name, int *len) {
271
28.5k
    int l = 0;
272
273
28.5k
    if (name == NULL) return(NULL);
274
28.5k
    if (len == NULL) return(NULL);
275
276
    /* nasty but valid */
277
28.5k
    if (name[0] == ':')
278
2.93k
  return(NULL);
279
280
    /*
281
     * we are not trying to validate but just to cut, and yes it will
282
     * work even if this is as set of UTF-8 encoded chars
283
     */
284
117k
    while ((name[l] != 0) && (name[l] != ':'))
285
91.5k
  l++;
286
287
25.6k
    if (name[l] == 0)
288
22.5k
  return(NULL);
289
290
3.09k
    *len = l;
291
292
3.09k
    return(&name[l+1]);
293
25.6k
}
294
295
const xmlChar *
296
45.7k
xmlSplitQName4(const xmlChar *name, xmlChar **prefixPtr) {
297
45.7k
    xmlChar *prefix;
298
45.7k
    int l = 0;
299
300
45.7k
    if ((name == NULL) || (prefixPtr == NULL))
301
0
        return(NULL);
302
303
45.7k
    *prefixPtr = NULL;
304
305
    /* nasty but valid */
306
45.7k
    if (name[0] == ':')
307
1.33k
  return(name);
308
309
    /*
310
     * we are not trying to validate but just to cut, and yes it will
311
     * work even if this is as set of UTF-8 encoded chars
312
     */
313
274k
    while ((name[l] != 0) && (name[l] != ':'))
314
230k
  l++;
315
316
    /*
317
     * TODO: What about names with multiple colons?
318
     */
319
44.4k
    if ((name[l] == 0) || (name[l+1] == 0))
320
34.4k
  return(name);
321
322
9.92k
    prefix = xmlStrndup(name, l);
323
9.92k
    if (prefix == NULL)
324
0
        return(NULL);
325
326
9.92k
    *prefixPtr = prefix;
327
9.92k
    return(&name[l+1]);
328
9.92k
}
329
330
/************************************************************************
331
 *                  *
332
 *    Check Name, NCName and QName strings      *
333
 *                  *
334
 ************************************************************************/
335
336
9.40k
#define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
337
338
/**
339
 * xmlValidateNCName:
340
 * @value: the value to check
341
 * @space: allow spaces in front and end of the string
342
 *
343
 * Check that a value conforms to the lexical space of NCName
344
 *
345
 * Returns 0 if this validates, a positive error code number otherwise
346
 *         and -1 in case of internal or API error.
347
 */
348
int
349
2.37k
xmlValidateNCName(const xmlChar *value, int space) {
350
2.37k
    const xmlChar *cur = value;
351
2.37k
    int c,l;
352
353
2.37k
    if (value == NULL)
354
0
        return(-1);
355
356
    /*
357
     * First quick algorithm for ASCII range
358
     */
359
2.37k
    if (space)
360
2.37k
  while (IS_BLANK_CH(*cur)) cur++;
361
2.37k
    if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
362
2.37k
  (*cur == '_'))
363
1.16k
  cur++;
364
1.20k
    else
365
1.20k
  goto try_complex;
366
4.14k
    while (((*cur >= 'a') && (*cur <= 'z')) ||
367
4.14k
     ((*cur >= 'A') && (*cur <= 'Z')) ||
368
4.14k
     ((*cur >= '0') && (*cur <= '9')) ||
369
4.14k
     (*cur == '_') || (*cur == '-') || (*cur == '.'))
370
2.98k
  cur++;
371
1.16k
    if (space)
372
1.16k
  while (IS_BLANK_CH(*cur)) cur++;
373
1.16k
    if (*cur == 0)
374
162
  return(0);
375
376
2.21k
try_complex:
377
    /*
378
     * Second check for chars outside the ASCII range
379
     */
380
2.21k
    cur = value;
381
2.21k
    c = CUR_SCHAR(cur, l);
382
2.21k
    if (space) {
383
2.21k
  while (IS_BLANK(c)) {
384
327
      cur += l;
385
327
      c = CUR_SCHAR(cur, l);
386
327
  }
387
2.21k
    }
388
2.21k
    if ((!IS_LETTER(c)) && (c != '_'))
389
693
  return(1);
390
1.51k
    cur += l;
391
1.51k
    c = CUR_SCHAR(cur, l);
392
6.51k
    while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
393
6.51k
     (c == '-') || (c == '_') || IS_COMBINING(c) ||
394
6.51k
     IS_EXTENDER(c)) {
395
4.99k
  cur += l;
396
4.99k
  c = CUR_SCHAR(cur, l);
397
4.99k
    }
398
1.51k
    if (space) {
399
1.51k
  while (IS_BLANK(c)) {
400
357
      cur += l;
401
357
      c = CUR_SCHAR(cur, l);
402
357
  }
403
1.51k
    }
404
1.51k
    if (c != 0)
405
1.17k
  return(1);
406
407
342
    return(0);
408
1.51k
}
409
410
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
411
/**
412
 * xmlValidateQName:
413
 * @value: the value to check
414
 * @space: allow spaces in front and end of the string
415
 *
416
 * Check that a value conforms to the lexical space of QName
417
 *
418
 * Returns 0 if this validates, a positive error code number otherwise
419
 *         and -1 in case of internal or API error.
420
 */
421
int
422
0
xmlValidateQName(const xmlChar *value, int space) {
423
0
    const xmlChar *cur = value;
424
0
    int c,l;
425
426
0
    if (value == NULL)
427
0
        return(-1);
428
    /*
429
     * First quick algorithm for ASCII range
430
     */
431
0
    if (space)
432
0
  while (IS_BLANK_CH(*cur)) cur++;
433
0
    if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
434
0
  (*cur == '_'))
435
0
  cur++;
436
0
    else
437
0
  goto try_complex;
438
0
    while (((*cur >= 'a') && (*cur <= 'z')) ||
439
0
     ((*cur >= 'A') && (*cur <= 'Z')) ||
440
0
     ((*cur >= '0') && (*cur <= '9')) ||
441
0
     (*cur == '_') || (*cur == '-') || (*cur == '.'))
442
0
  cur++;
443
0
    if (*cur == ':') {
444
0
  cur++;
445
0
  if (((*cur >= 'a') && (*cur <= 'z')) ||
446
0
      ((*cur >= 'A') && (*cur <= 'Z')) ||
447
0
      (*cur == '_'))
448
0
      cur++;
449
0
  else
450
0
      goto try_complex;
451
0
  while (((*cur >= 'a') && (*cur <= 'z')) ||
452
0
         ((*cur >= 'A') && (*cur <= 'Z')) ||
453
0
         ((*cur >= '0') && (*cur <= '9')) ||
454
0
         (*cur == '_') || (*cur == '-') || (*cur == '.'))
455
0
      cur++;
456
0
    }
457
0
    if (space)
458
0
  while (IS_BLANK_CH(*cur)) cur++;
459
0
    if (*cur == 0)
460
0
  return(0);
461
462
0
try_complex:
463
    /*
464
     * Second check for chars outside the ASCII range
465
     */
466
0
    cur = value;
467
0
    c = CUR_SCHAR(cur, l);
468
0
    if (space) {
469
0
  while (IS_BLANK(c)) {
470
0
      cur += l;
471
0
      c = CUR_SCHAR(cur, l);
472
0
  }
473
0
    }
474
0
    if ((!IS_LETTER(c)) && (c != '_'))
475
0
  return(1);
476
0
    cur += l;
477
0
    c = CUR_SCHAR(cur, l);
478
0
    while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
479
0
     (c == '-') || (c == '_') || IS_COMBINING(c) ||
480
0
     IS_EXTENDER(c)) {
481
0
  cur += l;
482
0
  c = CUR_SCHAR(cur, l);
483
0
    }
484
0
    if (c == ':') {
485
0
  cur += l;
486
0
  c = CUR_SCHAR(cur, l);
487
0
  if ((!IS_LETTER(c)) && (c != '_'))
488
0
      return(1);
489
0
  cur += l;
490
0
  c = CUR_SCHAR(cur, l);
491
0
  while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
492
0
         (c == '-') || (c == '_') || IS_COMBINING(c) ||
493
0
         IS_EXTENDER(c)) {
494
0
      cur += l;
495
0
      c = CUR_SCHAR(cur, l);
496
0
  }
497
0
    }
498
0
    if (space) {
499
0
  while (IS_BLANK(c)) {
500
0
      cur += l;
501
0
      c = CUR_SCHAR(cur, l);
502
0
  }
503
0
    }
504
0
    if (c != 0)
505
0
  return(1);
506
0
    return(0);
507
0
}
508
509
/**
510
 * xmlValidateName:
511
 * @value: the value to check
512
 * @space: allow spaces in front and end of the string
513
 *
514
 * Check that a value conforms to the lexical space of Name
515
 *
516
 * Returns 0 if this validates, a positive error code number otherwise
517
 *         and -1 in case of internal or API error.
518
 */
519
int
520
0
xmlValidateName(const xmlChar *value, int space) {
521
0
    const xmlChar *cur = value;
522
0
    int c,l;
523
524
0
    if (value == NULL)
525
0
        return(-1);
526
    /*
527
     * First quick algorithm for ASCII range
528
     */
529
0
    if (space)
530
0
  while (IS_BLANK_CH(*cur)) cur++;
531
0
    if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
532
0
  (*cur == '_') || (*cur == ':'))
533
0
  cur++;
534
0
    else
535
0
  goto try_complex;
536
0
    while (((*cur >= 'a') && (*cur <= 'z')) ||
537
0
     ((*cur >= 'A') && (*cur <= 'Z')) ||
538
0
     ((*cur >= '0') && (*cur <= '9')) ||
539
0
     (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
540
0
  cur++;
541
0
    if (space)
542
0
  while (IS_BLANK_CH(*cur)) cur++;
543
0
    if (*cur == 0)
544
0
  return(0);
545
546
0
try_complex:
547
    /*
548
     * Second check for chars outside the ASCII range
549
     */
550
0
    cur = value;
551
0
    c = CUR_SCHAR(cur, l);
552
0
    if (space) {
553
0
  while (IS_BLANK(c)) {
554
0
      cur += l;
555
0
      c = CUR_SCHAR(cur, l);
556
0
  }
557
0
    }
558
0
    if ((!IS_LETTER(c)) && (c != '_') && (c != ':'))
559
0
  return(1);
560
0
    cur += l;
561
0
    c = CUR_SCHAR(cur, l);
562
0
    while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
563
0
     (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) {
564
0
  cur += l;
565
0
  c = CUR_SCHAR(cur, l);
566
0
    }
567
0
    if (space) {
568
0
  while (IS_BLANK(c)) {
569
0
      cur += l;
570
0
      c = CUR_SCHAR(cur, l);
571
0
  }
572
0
    }
573
0
    if (c != 0)
574
0
  return(1);
575
0
    return(0);
576
0
}
577
578
/**
579
 * xmlValidateNMToken:
580
 * @value: the value to check
581
 * @space: allow spaces in front and end of the string
582
 *
583
 * Check that a value conforms to the lexical space of NMToken
584
 *
585
 * Returns 0 if this validates, a positive error code number otherwise
586
 *         and -1 in case of internal or API error.
587
 */
588
int
589
0
xmlValidateNMToken(const xmlChar *value, int space) {
590
0
    const xmlChar *cur = value;
591
0
    int c,l;
592
593
0
    if (value == NULL)
594
0
        return(-1);
595
    /*
596
     * First quick algorithm for ASCII range
597
     */
598
0
    if (space)
599
0
  while (IS_BLANK_CH(*cur)) cur++;
600
0
    if (((*cur >= 'a') && (*cur <= 'z')) ||
601
0
        ((*cur >= 'A') && (*cur <= 'Z')) ||
602
0
        ((*cur >= '0') && (*cur <= '9')) ||
603
0
        (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
604
0
  cur++;
605
0
    else
606
0
  goto try_complex;
607
0
    while (((*cur >= 'a') && (*cur <= 'z')) ||
608
0
     ((*cur >= 'A') && (*cur <= 'Z')) ||
609
0
     ((*cur >= '0') && (*cur <= '9')) ||
610
0
     (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
611
0
  cur++;
612
0
    if (space)
613
0
  while (IS_BLANK_CH(*cur)) cur++;
614
0
    if (*cur == 0)
615
0
  return(0);
616
617
0
try_complex:
618
    /*
619
     * Second check for chars outside the ASCII range
620
     */
621
0
    cur = value;
622
0
    c = CUR_SCHAR(cur, l);
623
0
    if (space) {
624
0
  while (IS_BLANK(c)) {
625
0
      cur += l;
626
0
      c = CUR_SCHAR(cur, l);
627
0
  }
628
0
    }
629
0
    if (!(IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
630
0
        (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)))
631
0
  return(1);
632
0
    cur += l;
633
0
    c = CUR_SCHAR(cur, l);
634
0
    while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
635
0
     (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) {
636
0
  cur += l;
637
0
  c = CUR_SCHAR(cur, l);
638
0
    }
639
0
    if (space) {
640
0
  while (IS_BLANK(c)) {
641
0
      cur += l;
642
0
      c = CUR_SCHAR(cur, l);
643
0
  }
644
0
    }
645
0
    if (c != 0)
646
0
  return(1);
647
0
    return(0);
648
0
}
649
#endif /* LIBXML_TREE_ENABLED */
650
651
/************************************************************************
652
 *                  *
653
 *    Allocation and deallocation of basic structures   *
654
 *                  *
655
 ************************************************************************/
656
657
/**
658
 * xmlSetBufferAllocationScheme:
659
 * @scheme:  allocation method to use
660
 *
661
 * Set the buffer allocation method.  Types are
662
 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
663
 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
664
 *                             improves performance
665
 */
666
void
667
0
xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
668
0
    if ((scheme == XML_BUFFER_ALLOC_EXACT) ||
669
0
        (scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
670
0
        (scheme == XML_BUFFER_ALLOC_HYBRID))
671
0
  xmlBufferAllocScheme = scheme;
672
0
}
673
674
/**
675
 * xmlGetBufferAllocationScheme:
676
 *
677
 * 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
 * XML_BUFFER_ALLOC_HYBRID - use exact sizes on small strings to keep memory usage tight
682
 *                            in normal usage, and doubleit on large strings to avoid
683
 *                            pathological performance.
684
 *
685
 * Returns the current allocation scheme
686
 */
687
xmlBufferAllocationScheme
688
0
xmlGetBufferAllocationScheme(void) {
689
0
    return(xmlBufferAllocScheme);
690
0
}
691
692
/**
693
 * xmlNewNs:
694
 * @node:  the element carrying the namespace
695
 * @href:  the URI associated
696
 * @prefix:  the prefix for the namespace
697
 *
698
 * Creation of a new Namespace. This function will refuse to create
699
 * a namespace with a similar prefix than an existing one present on this
700
 * node.
701
 * Note that for a default namespace, @prefix should be NULL.
702
 *
703
 * We use href==NULL in the case of an element creation where the namespace
704
 * was not defined.
705
 *
706
 * Returns a new namespace pointer or NULL
707
 */
708
xmlNsPtr
709
56.4k
xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
710
56.4k
    xmlNsPtr cur;
711
712
56.4k
    if ((node != NULL) && (node->type != XML_ELEMENT_NODE))
713
0
  return(NULL);
714
715
    /*
716
     * Allocate a new Namespace and fill the fields.
717
     */
718
56.4k
    cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
719
56.4k
    if (cur == NULL)
720
0
  return(NULL);
721
56.4k
    memset(cur, 0, sizeof(xmlNs));
722
56.4k
    cur->type = XML_LOCAL_NAMESPACE;
723
724
56.4k
    if (href != NULL) {
725
55.0k
  cur->href = xmlStrdup(href);
726
55.0k
        if (cur->href == NULL)
727
0
            goto error;
728
55.0k
    }
729
56.4k
    if (prefix != NULL) {
730
15.4k
  cur->prefix = xmlStrdup(prefix);
731
15.4k
        if (cur->prefix == NULL)
732
0
            goto error;
733
15.4k
    }
734
735
    /*
736
     * Add it at the end to preserve parsing order ...
737
     * and checks for existing use of the prefix
738
     */
739
56.4k
    if (node != NULL) {
740
33.9k
  if (node->nsDef == NULL) {
741
32.0k
      node->nsDef = cur;
742
32.0k
  } else {
743
1.90k
      xmlNsPtr prev = node->nsDef;
744
745
1.90k
      if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
746
1.90k
    (xmlStrEqual(prev->prefix, cur->prefix)))
747
0
                goto error;
748
2.58k
      while (prev->next != NULL) {
749
684
          prev = prev->next;
750
684
    if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
751
684
        (xmlStrEqual(prev->prefix, cur->prefix)))
752
0
                    goto error;
753
684
      }
754
1.90k
      prev->next = cur;
755
1.90k
  }
756
33.9k
    }
757
56.4k
    return(cur);
758
759
0
error:
760
0
    xmlFreeNs(cur);
761
0
    return(NULL);
762
56.4k
}
763
764
/**
765
 * xmlSetNs:
766
 * @node:  a node in the document
767
 * @ns:  a namespace pointer
768
 *
769
 * Associate a namespace to a node, a posteriori.
770
 */
771
void
772
27.2k
xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
773
27.2k
    if (node == NULL) {
774
0
  return;
775
0
    }
776
27.2k
    if ((node->type == XML_ELEMENT_NODE) ||
777
27.2k
        (node->type == XML_ATTRIBUTE_NODE))
778
27.2k
  node->ns = ns;
779
27.2k
}
780
781
/**
782
 * xmlFreeNs:
783
 * @cur:  the namespace pointer
784
 *
785
 * Free up the structures associated to a namespace
786
 */
787
void
788
71.0k
xmlFreeNs(xmlNsPtr cur) {
789
71.0k
    if (cur == NULL) {
790
0
  return;
791
0
    }
792
71.0k
    if (cur->href != NULL) xmlFree((char *) cur->href);
793
71.0k
    if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
794
71.0k
    xmlFree(cur);
795
71.0k
}
796
797
/**
798
 * xmlFreeNsList:
799
 * @cur:  the first namespace pointer
800
 *
801
 * Free up all the structures associated to the chained namespaces.
802
 */
803
void
804
64.8k
xmlFreeNsList(xmlNsPtr cur) {
805
64.8k
    xmlNsPtr next;
806
64.8k
    if (cur == NULL) {
807
0
  return;
808
0
    }
809
135k
    while (cur != NULL) {
810
71.0k
        next = cur->next;
811
71.0k
        xmlFreeNs(cur);
812
71.0k
  cur = next;
813
71.0k
    }
814
64.8k
}
815
816
/**
817
 * xmlNewDtd:
818
 * @doc:  the document pointer
819
 * @name:  the DTD name
820
 * @ExternalID:  the external ID
821
 * @SystemID:  the system ID
822
 *
823
 * Creation of a new DTD for the external subset. To create an
824
 * internal subset, use xmlCreateIntSubset().
825
 *
826
 * Returns a pointer to the new DTD structure
827
 */
828
xmlDtdPtr
829
xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
830
137
                    const xmlChar *ExternalID, const xmlChar *SystemID) {
831
137
    xmlDtdPtr cur;
832
833
137
    if ((doc != NULL) && (doc->extSubset != NULL)) {
834
0
  return(NULL);
835
0
    }
836
837
    /*
838
     * Allocate a new DTD and fill the fields.
839
     */
840
137
    cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
841
137
    if (cur == NULL)
842
0
  return(NULL);
843
137
    memset(cur, 0 , sizeof(xmlDtd));
844
137
    cur->type = XML_DTD_NODE;
845
846
137
    if (name != NULL) {
847
137
  cur->name = xmlStrdup(name);
848
137
        if (cur->name == NULL)
849
0
            goto error;
850
137
    }
851
137
    if (ExternalID != NULL) {
852
0
  cur->ExternalID = xmlStrdup(ExternalID);
853
0
        if (cur->ExternalID == NULL)
854
0
            goto error;
855
0
    }
856
137
    if (SystemID != NULL) {
857
0
  cur->SystemID = xmlStrdup(SystemID);
858
0
        if (cur->SystemID == NULL)
859
0
            goto error;
860
0
    }
861
137
    if (doc != NULL)
862
137
  doc->extSubset = cur;
863
137
    cur->doc = doc;
864
865
137
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
866
0
  xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
867
137
    return(cur);
868
869
0
error:
870
0
    xmlFreeDtd(cur);
871
0
    return(NULL);
872
137
}
873
874
/**
875
 * xmlGetIntSubset:
876
 * @doc:  the document pointer
877
 *
878
 * Get the internal subset of a document
879
 * Returns a pointer to the DTD structure or NULL if not found
880
 */
881
882
xmlDtdPtr
883
26.0k
xmlGetIntSubset(const xmlDoc *doc) {
884
26.0k
    xmlNodePtr cur;
885
886
26.0k
    if (doc == NULL)
887
0
  return(NULL);
888
26.0k
    cur = doc->children;
889
32.7k
    while (cur != NULL) {
890
13.2k
  if (cur->type == XML_DTD_NODE)
891
6.49k
      return((xmlDtdPtr) cur);
892
6.74k
  cur = cur->next;
893
6.74k
    }
894
19.5k
    return((xmlDtdPtr) doc->intSubset);
895
26.0k
}
896
897
/**
898
 * xmlCreateIntSubset:
899
 * @doc:  the document pointer
900
 * @name:  the DTD name
901
 * @ExternalID:  the external (PUBLIC) ID
902
 * @SystemID:  the system ID
903
 *
904
 * Create the internal subset of a document
905
 * Returns a pointer to the new DTD structure
906
 */
907
xmlDtdPtr
908
xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
909
7.63k
                   const xmlChar *ExternalID, const xmlChar *SystemID) {
910
7.63k
    xmlDtdPtr cur;
911
912
7.63k
    if (doc != NULL) {
913
7.63k
        cur = xmlGetIntSubset(doc);
914
7.63k
        if (cur != NULL)
915
0
            return(cur);
916
7.63k
    }
917
918
    /*
919
     * Allocate a new DTD and fill the fields.
920
     */
921
7.63k
    cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
922
7.63k
    if (cur == NULL)
923
0
  return(NULL);
924
7.63k
    memset(cur, 0, sizeof(xmlDtd));
925
7.63k
    cur->type = XML_DTD_NODE;
926
927
7.63k
    if (name != NULL) {
928
2.72k
  cur->name = xmlStrdup(name);
929
2.72k
  if (cur->name == NULL)
930
0
            goto error;
931
2.72k
    }
932
7.63k
    if (ExternalID != NULL) {
933
621
  cur->ExternalID = xmlStrdup(ExternalID);
934
621
  if (cur->ExternalID  == NULL)
935
0
            goto error;
936
621
    }
937
7.63k
    if (SystemID != NULL) {
938
31
  cur->SystemID = xmlStrdup(SystemID);
939
31
  if (cur->SystemID == NULL)
940
0
            goto error;
941
31
    }
942
7.63k
    if (doc != NULL) {
943
7.63k
  doc->intSubset = cur;
944
7.63k
  cur->parent = doc;
945
7.63k
  cur->doc = doc;
946
7.63k
  if (doc->children == NULL) {
947
7.56k
      doc->children = (xmlNodePtr) cur;
948
7.56k
      doc->last = (xmlNodePtr) cur;
949
7.56k
  } else {
950
64
      if (doc->type == XML_HTML_DOCUMENT_NODE) {
951
0
    xmlNodePtr prev;
952
953
0
    prev = doc->children;
954
0
    prev->prev = (xmlNodePtr) cur;
955
0
    cur->next = prev;
956
0
    doc->children = (xmlNodePtr) cur;
957
64
      } else {
958
64
    xmlNodePtr next;
959
960
64
    next = doc->children;
961
737
    while ((next != NULL) && (next->type != XML_ELEMENT_NODE))
962
673
        next = next->next;
963
64
    if (next == NULL) {
964
64
        cur->prev = doc->last;
965
64
        cur->prev->next = (xmlNodePtr) cur;
966
64
        cur->next = NULL;
967
64
        doc->last = (xmlNodePtr) cur;
968
64
    } else {
969
0
        cur->next = next;
970
0
        cur->prev = next->prev;
971
0
        if (cur->prev == NULL)
972
0
      doc->children = (xmlNodePtr) cur;
973
0
        else
974
0
      cur->prev->next = (xmlNodePtr) cur;
975
0
        next->prev = (xmlNodePtr) cur;
976
0
    }
977
64
      }
978
64
  }
979
7.63k
    }
980
981
7.63k
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
982
0
  xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
983
7.63k
    return(cur);
984
985
0
error:
986
0
    xmlFreeDtd(cur);
987
0
    return(NULL);
988
7.63k
}
989
990
/**
991
 * DICT_FREE:
992
 * @str:  a string
993
 *
994
 * Free a string if it is not owned by the "dict" dictionary in the
995
 * current scope
996
 */
997
#define DICT_FREE(str)            \
998
243k
  if ((str) && ((!dict) ||       \
999
194k
      (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
1000
122k
      xmlFree((char *)(str));
1001
1002
1003
/**
1004
 * DICT_COPY:
1005
 * @str:  a string
1006
 *
1007
 * Copy a string using a "dict" dictionary in the current scope,
1008
 * if available.
1009
 */
1010
#define DICT_COPY(str, cpy) \
1011
0
    if (str) { \
1012
0
  if (dict) { \
1013
0
      if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1014
0
    cpy = (xmlChar *) (str); \
1015
0
      else \
1016
0
    cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1017
0
  } else \
1018
0
      cpy = xmlStrdup((const xmlChar *)(str)); }
1019
1020
/**
1021
 * DICT_CONST_COPY:
1022
 * @str:  a string
1023
 *
1024
 * Copy a string using a "dict" dictionary in the current scope,
1025
 * if available.
1026
 */
1027
#define DICT_CONST_COPY(str, cpy) \
1028
0
    if (str) { \
1029
0
  if (dict) { \
1030
0
      if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1031
0
    cpy = (const xmlChar *) (str); \
1032
0
      else \
1033
0
    cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1034
0
  } else \
1035
0
      cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }
1036
1037
1038
/**
1039
 * xmlFreeDtd:
1040
 * @cur:  the DTD structure to free up
1041
 *
1042
 * Free a DTD structure.
1043
 */
1044
void
1045
7.76k
xmlFreeDtd(xmlDtdPtr cur) {
1046
7.76k
    xmlDictPtr dict = NULL;
1047
1048
7.76k
    if (cur == NULL) {
1049
0
  return;
1050
0
    }
1051
7.76k
    if (cur->doc != NULL) dict = cur->doc->dict;
1052
1053
7.76k
    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
1054
0
  xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
1055
1056
7.76k
    if (cur->children != NULL) {
1057
6.34k
  xmlNodePtr next, c = cur->children;
1058
1059
  /*
1060
   * Cleanup all nodes which are not part of the specific lists
1061
   * of notations, elements, attributes and entities.
1062
   */
1063
28.7k
        while (c != NULL) {
1064
22.4k
      next = c->next;
1065
22.4k
      if ((c->type != XML_NOTATION_NODE) &&
1066
22.4k
          (c->type != XML_ELEMENT_DECL) &&
1067
22.4k
    (c->type != XML_ATTRIBUTE_DECL) &&
1068
22.4k
    (c->type != XML_ENTITY_DECL)) {
1069
10.1k
    xmlUnlinkNode(c);
1070
10.1k
    xmlFreeNode(c);
1071
10.1k
      }
1072
22.4k
      c = next;
1073
22.4k
  }
1074
6.34k
    }
1075
7.76k
    DICT_FREE(cur->name)
1076
7.76k
    DICT_FREE(cur->SystemID)
1077
7.76k
    DICT_FREE(cur->ExternalID)
1078
    /* TODO !!! */
1079
7.76k
    if (cur->notations != NULL)
1080
78
        xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
1081
1082
7.76k
    if (cur->elements != NULL)
1083
3.77k
        xmlFreeElementTable((xmlElementTablePtr) cur->elements);
1084
7.76k
    if (cur->attributes != NULL)
1085
3.56k
        xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
1086
7.76k
    if (cur->entities != NULL)
1087
2.28k
        xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
1088
7.76k
    if (cur->pentities != NULL)
1089
2.34k
        xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->pentities);
1090
1091
7.76k
    xmlFree(cur);
1092
7.76k
}
1093
1094
/**
1095
 * xmlNewDoc:
1096
 * @version:  xmlChar string giving the version of XML "1.0"
1097
 *
1098
 * Creates a new XML document
1099
 *
1100
 * Returns a new document
1101
 */
1102
xmlDocPtr
1103
14.6k
xmlNewDoc(const xmlChar *version) {
1104
14.6k
    xmlDocPtr cur;
1105
1106
14.6k
    if (version == NULL)
1107
5.02k
  version = (const xmlChar *) "1.0";
1108
1109
    /*
1110
     * Allocate a new document and fill the fields.
1111
     */
1112
14.6k
    cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
1113
14.6k
    if (cur == NULL)
1114
0
  return(NULL);
1115
14.6k
    memset(cur, 0, sizeof(xmlDoc));
1116
14.6k
    cur->type = XML_DOCUMENT_NODE;
1117
1118
14.6k
    cur->version = xmlStrdup(version);
1119
14.6k
    if (cur->version == NULL) {
1120
0
  xmlFree(cur);
1121
0
  return(NULL);
1122
0
    }
1123
14.6k
    cur->standalone = -1;
1124
14.6k
    cur->compression = -1; /* not initialized */
1125
14.6k
    cur->doc = cur;
1126
14.6k
    cur->parseFlags = 0;
1127
14.6k
    cur->properties = XML_DOC_USERBUILT;
1128
    /*
1129
     * The in memory encoding is always UTF8
1130
     * This field will never change and would
1131
     * be obsolete if not for binary compatibility.
1132
     */
1133
14.6k
    cur->charset = XML_CHAR_ENCODING_UTF8;
1134
1135
14.6k
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1136
0
  xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
1137
14.6k
    return(cur);
1138
14.6k
}
1139
1140
/**
1141
 * xmlFreeDoc:
1142
 * @cur:  pointer to the document
1143
 *
1144
 * Free up all the structures used by a document, tree included.
1145
 */
1146
void
1147
22.3k
xmlFreeDoc(xmlDocPtr cur) {
1148
22.3k
    xmlDtdPtr extSubset, intSubset;
1149
22.3k
    xmlDictPtr dict = NULL;
1150
1151
22.3k
    if (cur == NULL) {
1152
7.66k
  return;
1153
7.66k
    }
1154
1155
14.6k
    if (cur != NULL) dict = cur->dict;
1156
1157
14.6k
    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
1158
0
  xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
1159
1160
    /*
1161
     * Do this before freeing the children list to avoid ID lookups
1162
     */
1163
14.6k
    if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
1164
14.6k
    cur->ids = NULL;
1165
14.6k
    if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
1166
14.6k
    cur->refs = NULL;
1167
14.6k
    extSubset = cur->extSubset;
1168
14.6k
    intSubset = cur->intSubset;
1169
14.6k
    if (intSubset == extSubset)
1170
7.03k
  extSubset = NULL;
1171
14.6k
    if (extSubset != NULL) {
1172
0
  xmlUnlinkNode((xmlNodePtr) cur->extSubset);
1173
0
  cur->extSubset = NULL;
1174
0
  xmlFreeDtd(extSubset);
1175
0
    }
1176
14.6k
    if (intSubset != NULL) {
1177
7.76k
  xmlUnlinkNode((xmlNodePtr) cur->intSubset);
1178
7.76k
  cur->intSubset = NULL;
1179
7.76k
  xmlFreeDtd(intSubset);
1180
7.76k
    }
1181
1182
14.6k
    if (cur->children != NULL) xmlFreeNodeList(cur->children);
1183
14.6k
    if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
1184
1185
14.6k
    DICT_FREE(cur->version)
1186
14.6k
    DICT_FREE(cur->name)
1187
14.6k
    DICT_FREE(cur->encoding)
1188
14.6k
    DICT_FREE(cur->URL)
1189
14.6k
    xmlFree(cur);
1190
14.6k
    if (dict) xmlDictFree(dict);
1191
14.6k
}
1192
1193
/**
1194
 * xmlStringLenGetNodeList:
1195
 * @doc:  the document
1196
 * @value:  the value of the text
1197
 * @len:  the length of the string value
1198
 *
1199
 * Parse the value string and build the node list associated. Should
1200
 * produce a flat tree with only TEXTs and ENTITY_REFs.
1201
 * Returns a pointer to the first child
1202
 */
1203
xmlNodePtr
1204
1.22k
xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) {
1205
1.22k
    xmlNodePtr ret = NULL, head = NULL, last = NULL;
1206
1.22k
    xmlNodePtr node;
1207
1.22k
    xmlChar *val = NULL;
1208
1.22k
    const xmlChar *cur, *end;
1209
1.22k
    const xmlChar *q;
1210
1.22k
    xmlEntityPtr ent;
1211
1.22k
    xmlBufPtr buf;
1212
1213
    /*
1214
     * This function should only receive valid attribute values that
1215
     * were checked by the parser, typically by xmlParseAttValueComplex
1216
     * calling xmlStringDecodeEntities.
1217
     *
1218
     * In recovery mode, the parser can produce invalid attribute
1219
     * values. For now, we ignore any errors silently. If this is fixed,
1220
     * we could add assertions here to catch parser issues.
1221
     */
1222
1223
1.22k
    if (value == NULL) return(NULL);
1224
1.22k
    cur = value;
1225
1.22k
    end = cur + len;
1226
1227
1.22k
    buf = xmlBufCreateSize(0);
1228
1.22k
    if (buf == NULL) return(NULL);
1229
1.22k
    xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
1230
1231
1.22k
    q = cur;
1232
32.4k
    while ((cur < end) && (*cur != 0)) {
1233
31.1k
  if (cur[0] == '&') {
1234
1.65k
      int charval = 0;
1235
1.65k
      xmlChar tmp;
1236
1237
      /*
1238
       * Save the current text.
1239
       */
1240
1.65k
            if (cur != q) {
1241
509
    if (xmlBufAdd(buf, q, cur - q))
1242
0
        goto out;
1243
509
      }
1244
1.65k
      q = cur;
1245
1.65k
      if ((cur + 2 < end) && (cur[1] == '#') && (cur[2] == 'x')) {
1246
0
    cur += 3;
1247
0
    if (cur < end)
1248
0
        tmp = *cur;
1249
0
    else
1250
0
        tmp = 0;
1251
0
    while (tmp != ';') { /* Non input consuming loop */
1252
0
        if ((tmp >= '0') && (tmp <= '9'))
1253
0
      charval = charval * 16 + (tmp - '0');
1254
0
        else if ((tmp >= 'a') && (tmp <= 'f'))
1255
0
      charval = charval * 16 + (tmp - 'a') + 10;
1256
0
        else if ((tmp >= 'A') && (tmp <= 'F'))
1257
0
      charval = charval * 16 + (tmp - 'A') + 10;
1258
0
        else {
1259
0
      charval = 0;
1260
0
      break;
1261
0
        }
1262
0
        cur++;
1263
0
        if (cur < end)
1264
0
      tmp = *cur;
1265
0
        else
1266
0
      tmp = 0;
1267
0
    }
1268
0
    if (tmp == ';')
1269
0
        cur++;
1270
0
    q = cur;
1271
1.65k
      } else if ((cur + 1 < end) && (cur[1] == '#')) {
1272
571
    cur += 2;
1273
571
    if (cur < end)
1274
571
        tmp = *cur;
1275
0
    else
1276
0
        tmp = 0;
1277
1.71k
    while (tmp != ';') { /* Non input consuming loops */
1278
                    /* Don't check for integer overflow, see above. */
1279
1.14k
        if ((tmp >= '0') && (tmp <= '9'))
1280
1.14k
      charval = charval * 10 + (tmp - '0');
1281
0
        else {
1282
0
      charval = 0;
1283
0
      break;
1284
0
        }
1285
1.14k
        cur++;
1286
1.14k
        if (cur < end)
1287
1.14k
      tmp = *cur;
1288
0
        else
1289
0
      tmp = 0;
1290
1.14k
    }
1291
571
    if (tmp == ';')
1292
571
        cur++;
1293
571
    q = cur;
1294
1.08k
      } else {
1295
    /*
1296
     * Read the entity string
1297
     */
1298
1.08k
    cur++;
1299
1.08k
    q = cur;
1300
2.17k
    while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++;
1301
1.08k
    if ((cur >= end) || (*cur == 0))
1302
0
        break;
1303
1.08k
    if (cur != q) {
1304
        /*
1305
         * Predefined entities don't generate nodes
1306
         */
1307
1.08k
        val = xmlStrndup(q, cur - q);
1308
1.08k
        ent = xmlGetDocEntity(doc, val);
1309
1.08k
        if ((ent != NULL) &&
1310
1.08k
      (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1311
1312
0
      if (xmlBufCat(buf, ent->content))
1313
0
          goto out;
1314
1.08k
        } else {
1315
      /*
1316
       * Flush buffer so far
1317
       */
1318
1.08k
      if (!xmlBufIsEmpty(buf)) {
1319
358
          node = xmlNewDocText(doc, NULL);
1320
358
          if (node == NULL)
1321
0
        goto out;
1322
358
          node->content = xmlBufDetach(buf);
1323
1324
358
          if (last == NULL) {
1325
138
        last = head = node;
1326
220
          } else {
1327
220
        last = xmlAddNextSibling(last, node);
1328
220
          }
1329
358
      }
1330
1331
      /*
1332
       * Create a new REFERENCE_REF node
1333
       */
1334
1.08k
      node = xmlNewReference(doc, val);
1335
1.08k
      if (node == NULL)
1336
0
          goto out;
1337
1.08k
      else if ((ent != NULL) &&
1338
1.08k
                                 ((ent->flags & XML_ENT_PARSED) == 0) &&
1339
1.08k
                                 ((ent->flags & XML_ENT_EXPANDING) == 0)) {
1340
104
          xmlNodePtr temp;
1341
1342
                            /*
1343
                             * The entity should have been checked already,
1344
                             * but set the flag anyway to avoid recursion.
1345
                             */
1346
104
                            if (node->content != NULL) {
1347
104
                                ent->flags |= XML_ENT_EXPANDING;
1348
104
                                ent->children = xmlStringGetNodeList(doc,
1349
104
                                        node->content);
1350
104
                                ent->flags &= ~XML_ENT_EXPANDING;
1351
104
                                if (ent->children == NULL) {
1352
0
                                    xmlFreeNode(node);
1353
0
                                    goto out;
1354
0
                                }
1355
104
                            }
1356
104
                            ent->flags |= XML_ENT_PARSED;
1357
104
          temp = ent->children;
1358
712
          while (temp) {
1359
608
        temp->parent = (xmlNodePtr)ent;
1360
608
        ent->last = temp;
1361
608
        temp = temp->next;
1362
608
          }
1363
104
      }
1364
1.08k
      if (last == NULL) {
1365
142
          last = head = node;
1366
943
      } else {
1367
943
          last = xmlAddNextSibling(last, node);
1368
943
      }
1369
1.08k
        }
1370
1.08k
        xmlFree(val);
1371
1.08k
                    val = NULL;
1372
1.08k
    }
1373
1.08k
    cur++;
1374
1.08k
    q = cur;
1375
1.08k
      }
1376
1.65k
      if (charval != 0) {
1377
571
    xmlChar buffer[10];
1378
571
    int l;
1379
1380
571
    l = xmlCopyCharMultiByte(buffer, charval);
1381
571
    buffer[l] = 0;
1382
1383
571
    if (xmlBufCat(buf, buffer))
1384
0
        goto out;
1385
571
    charval = 0;
1386
571
      }
1387
1.65k
  } else
1388
29.5k
      cur++;
1389
31.1k
    }
1390
1391
1.22k
    if (cur != q) {
1392
        /*
1393
   * Handle the last piece of text.
1394
   */
1395
1.05k
  if (xmlBufAdd(buf, q, cur - q))
1396
0
      goto out;
1397
1.05k
    }
1398
1399
1.22k
    if (!xmlBufIsEmpty(buf)) {
1400
1.08k
  node = xmlNewDocText(doc, NULL);
1401
1.08k
  if (node == NULL)
1402
0
            goto out;
1403
1.08k
  node->content = xmlBufDetach(buf);
1404
1405
1.08k
  if (last == NULL) {
1406
947
      head = node;
1407
947
  } else {
1408
134
      xmlAddNextSibling(last, node);
1409
134
  }
1410
1.08k
    } else if (head == NULL) {
1411
0
        head = xmlNewDocText(doc, BAD_CAST "");
1412
0
    }
1413
1414
1.22k
    ret = head;
1415
1.22k
    head = NULL;
1416
1417
1.22k
out:
1418
1.22k
    xmlBufFree(buf);
1419
1.22k
    if (val != NULL)
1420
0
        xmlFree(val);
1421
1.22k
    if (head != NULL)
1422
0
        xmlFreeNodeList(head);
1423
1.22k
    return(ret);
1424
1.22k
}
1425
1426
/**
1427
 * xmlStringGetNodeList:
1428
 * @doc:  the document
1429
 * @value:  the value of the attribute
1430
 *
1431
 * Parse the value string and build the node list associated. Should
1432
 * produce a flat tree with only TEXTs and ENTITY_REFs.
1433
 * Returns a pointer to the first child
1434
 */
1435
xmlNodePtr
1436
3.38k
xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) {
1437
3.38k
    xmlNodePtr ret = NULL, head = NULL, last = NULL;
1438
3.38k
    xmlNodePtr node;
1439
3.38k
    xmlChar *val = NULL;
1440
3.38k
    const xmlChar *cur = value;
1441
3.38k
    const xmlChar *q;
1442
3.38k
    xmlEntityPtr ent;
1443
3.38k
    xmlBufPtr buf;
1444
1445
    /*
1446
     * This function should only receive valid attribute values that
1447
     * were checked by the parser, typically by xmlParseAttValueComplex
1448
     * calling xmlStringDecodeEntities.
1449
     *
1450
     * In recovery mode, the parser can produce invalid attribute
1451
     * values. For now, we ignore any errors silently. If this is fixed,
1452
     * we could add assertions here to catch parser issues.
1453
     */
1454
1455
3.38k
    if (value == NULL) return(NULL);
1456
1457
3.38k
    buf = xmlBufCreateSize(0);
1458
3.38k
    if (buf == NULL) return(NULL);
1459
3.38k
    xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
1460
1461
3.38k
    q = cur;
1462
42.2k
    while (*cur != 0) {
1463
38.8k
  if (cur[0] == '&') {
1464
2.24k
      int charval = 0;
1465
2.24k
      xmlChar tmp;
1466
1467
      /*
1468
       * Save the current text.
1469
       */
1470
2.24k
            if (cur != q) {
1471
713
    if (xmlBufAdd(buf, q, cur - q))
1472
0
        goto out;
1473
713
      }
1474
2.24k
      q = cur;
1475
2.24k
      if ((cur[1] == '#') && (cur[2] == 'x')) {
1476
193
    cur += 3;
1477
193
    tmp = *cur;
1478
1.17k
    while (tmp != ';') { /* Non input consuming loop */
1479
982
        if ((tmp >= '0') && (tmp <= '9'))
1480
310
      charval = charval * 16 + (tmp - '0');
1481
672
        else if ((tmp >= 'a') && (tmp <= 'f'))
1482
131
      charval = charval * 16 + (tmp - 'a') + 10;
1483
541
        else if ((tmp >= 'A') && (tmp <= 'F'))
1484
541
      charval = charval * 16 + (tmp - 'A') + 10;
1485
0
        else {
1486
0
      charval = 0;
1487
0
      break;
1488
0
        }
1489
982
        cur++;
1490
982
        tmp = *cur;
1491
982
    }
1492
193
    if (tmp == ';')
1493
193
        cur++;
1494
193
    q = cur;
1495
2.05k
      } else if  (cur[1] == '#') {
1496
357
    cur += 2;
1497
357
    tmp = *cur;
1498
1.07k
    while (tmp != ';') { /* Non input consuming loops */
1499
                    /* Don't check for integer overflow, see above. */
1500
714
        if ((tmp >= '0') && (tmp <= '9'))
1501
714
      charval = charval * 10 + (tmp - '0');
1502
0
        else {
1503
0
      charval = 0;
1504
0
      break;
1505
0
        }
1506
714
        cur++;
1507
714
        tmp = *cur;
1508
714
    }
1509
357
    if (tmp == ';')
1510
357
        cur++;
1511
357
    q = cur;
1512
1.69k
      } else {
1513
    /*
1514
     * Read the entity string
1515
     */
1516
1.69k
    cur++;
1517
1.69k
    q = cur;
1518
4.20k
    while ((*cur != 0) && (*cur != ';')) cur++;
1519
1.69k
    if (*cur == 0)
1520
0
        break;
1521
1.69k
    if (cur != q) {
1522
        /*
1523
         * Predefined entities don't generate nodes
1524
         */
1525
1.69k
        val = xmlStrndup(q, cur - q);
1526
1.69k
                    if (val == NULL)
1527
0
                        goto out;
1528
1.69k
        ent = xmlGetDocEntity(doc, val);
1529
1.69k
        if ((ent != NULL) &&
1530
1.69k
      (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1531
1532
196
      if (xmlBufCat(buf, ent->content))
1533
0
          goto out;
1534
1535
1.49k
        } else {
1536
      /*
1537
       * Flush buffer so far
1538
       */
1539
1.49k
      if (!xmlBufIsEmpty(buf)) {
1540
435
          node = xmlNewDocText(doc, NULL);
1541
435
                            if (node == NULL)
1542
0
                                goto out;
1543
435
          node->content = xmlBufDetach(buf);
1544
1545
435
          if (last == NULL) {
1546
174
        last = head = node;
1547
261
          } else {
1548
261
        last = xmlAddNextSibling(last, node);
1549
261
          }
1550
435
      }
1551
1552
      /*
1553
       * Create a new REFERENCE_REF node
1554
       */
1555
1.49k
      node = xmlNewReference(doc, val);
1556
1.49k
      if (node == NULL)
1557
0
          goto out;
1558
1.49k
      if ((ent != NULL) &&
1559
1.49k
                            ((ent->flags & XML_ENT_PARSED) == 0) &&
1560
1.49k
                            ((ent->flags & XML_ENT_EXPANDING) == 0)) {
1561
76
          xmlNodePtr temp;
1562
1563
                            /*
1564
                             * The entity should have been checked already,
1565
                             * but set the flag anyway to avoid recursion.
1566
                             */
1567
76
                            if (node->content != NULL) {
1568
75
                                ent->flags |= XML_ENT_EXPANDING;
1569
75
                                ent->children = xmlStringGetNodeList(doc,
1570
75
                                        node->content);
1571
75
                                ent->flags &= ~XML_ENT_EXPANDING;
1572
75
                                if (ent->children == NULL) {
1573
0
                                    xmlFreeNode(node);
1574
0
                                    goto out;
1575
0
                                }
1576
75
                            }
1577
76
                            ent->flags |= XML_ENT_PARSED;
1578
76
          temp = ent->children;
1579
453
          while (temp) {
1580
377
        temp->parent = (xmlNodePtr)ent;
1581
377
        ent->last = temp;
1582
377
        temp = temp->next;
1583
377
          }
1584
76
      }
1585
1.49k
      if (last == NULL) {
1586
130
          last = head = node;
1587
1.36k
      } else {
1588
1.36k
          last = xmlAddNextSibling(last, node);
1589
1.36k
      }
1590
1.49k
        }
1591
1.69k
        xmlFree(val);
1592
1.69k
                    val = NULL;
1593
1.69k
    }
1594
1.69k
    cur++;
1595
1.69k
    q = cur;
1596
1.69k
      }
1597
2.24k
      if (charval != 0) {
1598
550
    xmlChar buffer[10];
1599
550
    int len;
1600
1601
550
    len = xmlCopyCharMultiByte(buffer, charval);
1602
550
    buffer[len] = 0;
1603
1604
550
    if (xmlBufCat(buf, buffer))
1605
0
        goto out;
1606
550
    charval = 0;
1607
550
      }
1608
2.24k
  } else
1609
36.6k
      cur++;
1610
38.8k
    }
1611
3.38k
    if ((cur != q) || (head == NULL)) {
1612
        /*
1613
   * Handle the last piece of text.
1614
   */
1615
3.24k
  xmlBufAdd(buf, q, cur - q);
1616
3.24k
    }
1617
1618
3.38k
    if (xmlBufIsEmpty(buf) <= 0) {
1619
3.21k
  node = xmlNewDocText(doc, NULL);
1620
3.21k
        if (node == NULL)
1621
0
            goto out;
1622
3.21k
  node->content = xmlBufDetach(buf);
1623
3.21k
        if (node->content == NULL) {
1624
0
            xmlFreeNode(node);
1625
0
            goto out;
1626
0
        }
1627
1628
3.21k
  if (last == NULL) {
1629
3.05k
      head = node;
1630
3.05k
  } else {
1631
159
      xmlAddNextSibling(last, node);
1632
159
  }
1633
3.21k
    } else if (head == NULL) {
1634
23
        head = xmlNewDocText(doc, BAD_CAST "");
1635
23
    }
1636
1637
3.38k
    ret = head;
1638
3.38k
    head = NULL;
1639
1640
3.38k
out:
1641
3.38k
    xmlBufFree(buf);
1642
3.38k
    if (val != NULL) xmlFree(val);
1643
3.38k
    if (head != NULL) xmlFreeNodeList(head);
1644
3.38k
    return(ret);
1645
3.38k
}
1646
1647
/**
1648
 * xmlNodeListGetString:
1649
 * @doc:  the document
1650
 * @list:  a Node list
1651
 * @inLine:  should we replace entity contents or show their external form
1652
 *
1653
 * Build the string equivalent to the text contained in the Node list
1654
 * made of TEXTs and ENTITY_REFs
1655
 *
1656
 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1657
 */
1658
xmlChar *
1659
xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine)
1660
0
{
1661
0
    const xmlNode *node = list;
1662
0
    xmlChar *ret = NULL;
1663
0
    xmlEntityPtr ent;
1664
0
    int attr;
1665
1666
0
    if (list == NULL)
1667
0
        return xmlStrdup(BAD_CAST "");
1668
0
    if ((list->parent != NULL) && (list->parent->type == XML_ATTRIBUTE_NODE))
1669
0
        attr = 1;
1670
0
    else
1671
0
        attr = 0;
1672
1673
0
    while (node != NULL) {
1674
0
        if ((node->type == XML_TEXT_NODE) ||
1675
0
            (node->type == XML_CDATA_SECTION_NODE)) {
1676
0
            if (inLine) {
1677
0
                ret = xmlStrcat(ret, node->content);
1678
0
                if (ret == NULL)
1679
0
                    goto error;
1680
0
            } else {
1681
0
                xmlChar *buffer;
1682
1683
0
    if (attr)
1684
0
        buffer = xmlEncodeAttributeEntities(doc, node->content);
1685
0
    else
1686
0
        buffer = xmlEncodeEntitiesReentrant(doc, node->content);
1687
0
                if (buffer == NULL)
1688
0
                    goto error;
1689
0
                ret = xmlStrcat(ret, buffer);
1690
0
                xmlFree(buffer);
1691
0
                if (ret == NULL)
1692
0
                    goto error;
1693
0
            }
1694
0
        } else if (node->type == XML_ENTITY_REF_NODE) {
1695
0
            if (inLine) {
1696
0
                ent = xmlGetDocEntity(doc, node->name);
1697
0
                if (ent != NULL) {
1698
0
                    if (ent->children != NULL) {
1699
0
                        xmlChar *buffer;
1700
1701
                        /* an entity content can be any "well balanced chunk",
1702
                         * i.e. the result of the content [43] production:
1703
                         * http://www.w3.org/TR/REC-xml#NT-content.
1704
                         * So it can contain text, CDATA section or nested
1705
                         * entity reference nodes (among others).
1706
                         * -> we recursive  call xmlNodeListGetString()
1707
                         * which handles these types */
1708
0
                        buffer = xmlNodeListGetString(doc, ent->children, 1);
1709
0
                        if (buffer == NULL)
1710
0
                            goto error;
1711
0
                        ret = xmlStrcat(ret, buffer);
1712
0
                        xmlFree(buffer);
1713
0
                        if (ret == NULL)
1714
0
                            goto error;
1715
0
                    }
1716
0
                } else if (node->content != NULL) {
1717
0
                    ret = xmlStrcat(ret, node->content);
1718
0
                    if (ret == NULL)
1719
0
                        goto error;
1720
0
                }
1721
0
            } else {
1722
0
                xmlChar buf[2];
1723
1724
0
                buf[0] = '&';
1725
0
                buf[1] = 0;
1726
0
                ret = xmlStrncat(ret, buf, 1);
1727
0
                ret = xmlStrcat(ret, node->name);
1728
0
                buf[0] = ';';
1729
0
                buf[1] = 0;
1730
0
                ret = xmlStrncat(ret, buf, 1);
1731
0
                if (ret == NULL)
1732
0
                    goto error;
1733
0
            }
1734
0
        }
1735
0
        node = node->next;
1736
0
    }
1737
0
    if (ret == NULL)
1738
0
        ret = xmlStrdup(BAD_CAST "");
1739
0
    return (ret);
1740
1741
0
error:
1742
0
    xmlFree(ret);
1743
0
    return(NULL);
1744
0
}
1745
1746
#ifdef LIBXML_TREE_ENABLED
1747
/**
1748
 * xmlNodeListGetRawString:
1749
 * @doc:  the document
1750
 * @list:  a Node list
1751
 * @inLine:  should we replace entity contents or show their external form
1752
 *
1753
 * Builds the string equivalent to the text contained in the Node list
1754
 * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
1755
 * this function doesn't do any character encoding handling.
1756
 *
1757
 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1758
 */
1759
xmlChar *
1760
xmlNodeListGetRawString(const xmlDoc *doc, const xmlNode *list, int inLine)
1761
0
{
1762
0
    const xmlNode *node = list;
1763
0
    xmlChar *ret = NULL;
1764
0
    xmlEntityPtr ent;
1765
1766
0
    if (list == NULL)
1767
0
        return xmlStrdup(BAD_CAST "");
1768
1769
0
    while (node != NULL) {
1770
0
        if ((node->type == XML_TEXT_NODE) ||
1771
0
            (node->type == XML_CDATA_SECTION_NODE)) {
1772
0
            if (inLine) {
1773
0
                ret = xmlStrcat(ret, node->content);
1774
0
            } else {
1775
0
                xmlChar *buffer;
1776
1777
0
                buffer = xmlEncodeSpecialChars(doc, node->content);
1778
0
                if (buffer != NULL) {
1779
0
                    ret = xmlStrcat(ret, buffer);
1780
0
                    xmlFree(buffer);
1781
0
                }
1782
0
            }
1783
0
        } else if (node->type == XML_ENTITY_REF_NODE) {
1784
0
            if (inLine) {
1785
0
                ent = xmlGetDocEntity(doc, node->name);
1786
0
                if (ent != NULL) {
1787
0
                    xmlChar *buffer;
1788
1789
                    /* an entity content can be any "well balanced chunk",
1790
                     * i.e. the result of the content [43] production:
1791
                     * http://www.w3.org/TR/REC-xml#NT-content.
1792
                     * So it can contain text, CDATA section or nested
1793
                     * entity reference nodes (among others).
1794
                     * -> we recursive  call xmlNodeListGetRawString()
1795
                     * which handles these types */
1796
0
                    buffer =
1797
0
                        xmlNodeListGetRawString(doc, ent->children, 1);
1798
0
                    if (buffer != NULL) {
1799
0
                        ret = xmlStrcat(ret, buffer);
1800
0
                        xmlFree(buffer);
1801
0
                    }
1802
0
                } else {
1803
0
                    ret = xmlStrcat(ret, node->content);
1804
0
                }
1805
0
            } else {
1806
0
                xmlChar buf[2];
1807
1808
0
                buf[0] = '&';
1809
0
                buf[1] = 0;
1810
0
                ret = xmlStrncat(ret, buf, 1);
1811
0
                ret = xmlStrcat(ret, node->name);
1812
0
                buf[0] = ';';
1813
0
                buf[1] = 0;
1814
0
                ret = xmlStrncat(ret, buf, 1);
1815
0
            }
1816
0
        }
1817
0
        node = node->next;
1818
0
    }
1819
0
    if (ret == NULL)
1820
0
        ret = xmlStrdup(BAD_CAST "");
1821
0
    return (ret);
1822
0
}
1823
#endif /* LIBXML_TREE_ENABLED */
1824
1825
static xmlAttrPtr
1826
xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
1827
                   const xmlChar * name, const xmlChar * value,
1828
                   int eatname)
1829
4.55k
{
1830
4.55k
    xmlAttrPtr cur;
1831
4.55k
    xmlDocPtr doc = NULL;
1832
1833
4.55k
    if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) {
1834
0
        if ((eatname == 1) &&
1835
0
      ((node->doc == NULL) || (node->doc->dict == NULL) ||
1836
0
       (!(xmlDictOwns(node->doc->dict, name)))))
1837
0
            xmlFree((xmlChar *) name);
1838
0
        return (NULL);
1839
0
    }
1840
1841
    /*
1842
     * Allocate a new property and fill the fields.
1843
     */
1844
4.55k
    cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1845
4.55k
    if (cur == NULL) {
1846
0
        if ((eatname == 1) &&
1847
0
      ((node == NULL) || (node->doc == NULL) ||
1848
0
             (node->doc->dict == NULL) ||
1849
0
       (!(xmlDictOwns(node->doc->dict, name)))))
1850
0
            xmlFree((xmlChar *) name);
1851
0
        return (NULL);
1852
0
    }
1853
4.55k
    memset(cur, 0, sizeof(xmlAttr));
1854
4.55k
    cur->type = XML_ATTRIBUTE_NODE;
1855
1856
4.55k
    cur->parent = node;
1857
4.55k
    if (node != NULL) {
1858
4.55k
        doc = node->doc;
1859
4.55k
        cur->doc = doc;
1860
4.55k
    }
1861
4.55k
    cur->ns = ns;
1862
1863
4.55k
    if (eatname == 0) {
1864
0
        if ((doc != NULL) && (doc->dict != NULL))
1865
0
            cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
1866
0
        else
1867
0
            cur->name = xmlStrdup(name);
1868
0
        if (cur->name == NULL)
1869
0
            goto error;
1870
0
    } else
1871
4.55k
        cur->name = name;
1872
1873
4.55k
    if (value != NULL) {
1874
0
        xmlNodePtr tmp;
1875
1876
0
        cur->children = xmlNewDocText(doc, value);
1877
0
        if (cur->children == NULL)
1878
0
            goto error;
1879
0
        cur->last = NULL;
1880
0
        tmp = cur->children;
1881
0
        while (tmp != NULL) {
1882
0
            tmp->parent = (xmlNodePtr) cur;
1883
0
            if (tmp->next == NULL)
1884
0
                cur->last = tmp;
1885
0
            tmp = tmp->next;
1886
0
        }
1887
0
    }
1888
1889
4.55k
    if ((value != NULL) && (node != NULL) &&
1890
4.55k
        (xmlIsID(node->doc, node, cur) == 1) &&
1891
4.55k
        (xmlAddIDSafe(node->doc, value, cur, 0, NULL) < 0))
1892
0
        goto error;
1893
1894
    /*
1895
     * Add it at the end to preserve parsing order ...
1896
     */
1897
4.55k
    if (node != NULL) {
1898
4.55k
        if (node->properties == NULL) {
1899
3.44k
            node->properties = cur;
1900
3.44k
        } else {
1901
1.10k
            xmlAttrPtr prev = node->properties;
1902
1903
3.92k
            while (prev->next != NULL)
1904
2.82k
                prev = prev->next;
1905
1.10k
            prev->next = cur;
1906
1.10k
            cur->prev = prev;
1907
1.10k
        }
1908
4.55k
    }
1909
1910
4.55k
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1911
0
        xmlRegisterNodeDefaultValue((xmlNodePtr) cur);
1912
4.55k
    return (cur);
1913
1914
0
error:
1915
0
    xmlFreeProp(cur);
1916
0
    return(NULL);
1917
4.55k
}
1918
1919
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
1920
    defined(LIBXML_SCHEMAS_ENABLED)
1921
/**
1922
 * xmlNewProp:
1923
 * @node:  the holding node
1924
 * @name:  the name of the attribute
1925
 * @value:  the value of the attribute
1926
 *
1927
 * Create a new property carried by a node.
1928
 * Returns a pointer to the attribute
1929
 */
1930
xmlAttrPtr
1931
0
xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
1932
1933
0
    if (name == NULL) {
1934
0
  return(NULL);
1935
0
    }
1936
1937
0
  return xmlNewPropInternal(node, NULL, name, value, 0);
1938
0
}
1939
#endif /* LIBXML_TREE_ENABLED */
1940
1941
/**
1942
 * xmlNewNsProp:
1943
 * @node:  the holding node
1944
 * @ns:  the namespace
1945
 * @name:  the name of the attribute
1946
 * @value:  the value of the attribute
1947
 *
1948
 * Create a new property tagged with a namespace and carried by a node.
1949
 * Returns a pointer to the attribute
1950
 */
1951
xmlAttrPtr
1952
xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
1953
0
           const xmlChar *value) {
1954
1955
0
    if (name == NULL) {
1956
0
  return(NULL);
1957
0
    }
1958
1959
0
    return xmlNewPropInternal(node, ns, name, value, 0);
1960
0
}
1961
1962
/**
1963
 * xmlNewNsPropEatName:
1964
 * @node:  the holding node
1965
 * @ns:  the namespace
1966
 * @name:  the name of the attribute
1967
 * @value:  the value of the attribute
1968
 *
1969
 * Create a new property tagged with a namespace and carried by a node.
1970
 * Returns a pointer to the attribute
1971
 */
1972
xmlAttrPtr
1973
xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name,
1974
4.55k
           const xmlChar *value) {
1975
1976
4.55k
    if (name == NULL) {
1977
0
  return(NULL);
1978
0
    }
1979
1980
4.55k
    return xmlNewPropInternal(node, ns, name, value, 1);
1981
4.55k
}
1982
1983
/**
1984
 * xmlNewDocProp:
1985
 * @doc:  the document
1986
 * @name:  the name of the attribute
1987
 * @value:  the value of the attribute
1988
 *
1989
 * Create a new property carried by a document.
1990
 * NOTE: @value is supposed to be a piece of XML CDATA, so it allows entity
1991
 *       references, but XML special chars need to be escaped first by using
1992
 *       xmlEncodeEntitiesReentrant(). Use xmlNewProp() if you don't need
1993
 *       entities support.
1994
 *
1995
 * Returns a pointer to the attribute
1996
 */
1997
xmlAttrPtr
1998
0
xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
1999
0
    xmlAttrPtr cur;
2000
2001
0
    if (name == NULL) {
2002
0
  return(NULL);
2003
0
    }
2004
2005
    /*
2006
     * Allocate a new property and fill the fields.
2007
     */
2008
0
    cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
2009
0
    if (cur == NULL)
2010
0
  return(NULL);
2011
0
    memset(cur, 0, sizeof(xmlAttr));
2012
0
    cur->type = XML_ATTRIBUTE_NODE;
2013
2014
0
    if ((doc != NULL) && (doc->dict != NULL))
2015
0
  cur->name = xmlDictLookup(doc->dict, name, -1);
2016
0
    else
2017
0
  cur->name = xmlStrdup(name);
2018
0
    if (cur->name == NULL)
2019
0
        goto error;
2020
0
    cur->doc = doc;
2021
0
    if (value != NULL) {
2022
0
  xmlNodePtr tmp;
2023
2024
0
  cur->children = xmlStringGetNodeList(doc, value);
2025
0
  cur->last = NULL;
2026
2027
0
  tmp = cur->children;
2028
0
  while (tmp != NULL) {
2029
0
      tmp->parent = (xmlNodePtr) cur;
2030
0
      if (tmp->next == NULL)
2031
0
    cur->last = tmp;
2032
0
      tmp = tmp->next;
2033
0
  }
2034
0
    }
2035
2036
0
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2037
0
  xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
2038
0
    return(cur);
2039
2040
0
error:
2041
0
    xmlFreeProp(cur);
2042
0
    return(NULL);
2043
0
}
2044
2045
/**
2046
 * xmlFreePropList:
2047
 * @cur:  the first property in the list
2048
 *
2049
 * Free a property and all its siblings, all the children are freed too.
2050
 */
2051
void
2052
7.76k
xmlFreePropList(xmlAttrPtr cur) {
2053
7.76k
    xmlAttrPtr next;
2054
7.76k
    if (cur == NULL) return;
2055
20.7k
    while (cur != NULL) {
2056
12.9k
        next = cur->next;
2057
12.9k
        xmlFreeProp(cur);
2058
12.9k
  cur = next;
2059
12.9k
    }
2060
7.76k
}
2061
2062
/**
2063
 * xmlFreeProp:
2064
 * @cur:  an attribute
2065
 *
2066
 * Free one attribute, all the content is freed too
2067
 */
2068
void
2069
12.9k
xmlFreeProp(xmlAttrPtr cur) {
2070
12.9k
    xmlDictPtr dict = NULL;
2071
12.9k
    if (cur == NULL) return;
2072
2073
12.9k
    if (cur->doc != NULL) dict = cur->doc->dict;
2074
2075
12.9k
    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
2076
0
  xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
2077
2078
    /* Check for ID removal -> leading to invalid references ! */
2079
12.9k
    if ((cur->doc != NULL) && (cur->atype == XML_ATTRIBUTE_ID)) {
2080
2.49k
      xmlRemoveID(cur->doc, cur);
2081
2.49k
    }
2082
12.9k
    if (cur->children != NULL) xmlFreeNodeList(cur->children);
2083
12.9k
    DICT_FREE(cur->name)
2084
12.9k
    xmlFree(cur);
2085
12.9k
}
2086
2087
/**
2088
 * xmlRemoveProp:
2089
 * @cur:  an attribute
2090
 *
2091
 * Unlink and free one attribute, all the content is freed too
2092
 * Note this doesn't work for namespace definition attributes
2093
 *
2094
 * Returns 0 if success and -1 in case of error.
2095
 */
2096
int
2097
0
xmlRemoveProp(xmlAttrPtr cur) {
2098
0
    xmlAttrPtr tmp;
2099
0
    if (cur == NULL) {
2100
0
  return(-1);
2101
0
    }
2102
0
    if (cur->parent == NULL) {
2103
0
  return(-1);
2104
0
    }
2105
0
    tmp = cur->parent->properties;
2106
0
    if (tmp == cur) {
2107
0
        cur->parent->properties = cur->next;
2108
0
    if (cur->next != NULL)
2109
0
      cur->next->prev = NULL;
2110
0
  xmlFreeProp(cur);
2111
0
  return(0);
2112
0
    }
2113
0
    while (tmp != NULL) {
2114
0
  if (tmp->next == cur) {
2115
0
      tmp->next = cur->next;
2116
0
      if (tmp->next != NULL)
2117
0
    tmp->next->prev = tmp;
2118
0
      xmlFreeProp(cur);
2119
0
      return(0);
2120
0
  }
2121
0
        tmp = tmp->next;
2122
0
    }
2123
0
    return(-1);
2124
0
}
2125
2126
/**
2127
 * xmlNewDocPI:
2128
 * @doc:  the target document
2129
 * @name:  the processing instruction name
2130
 * @content:  the PI content
2131
 *
2132
 * Creation of a processing instruction element.
2133
 * Returns a pointer to the new node object.
2134
 */
2135
xmlNodePtr
2136
8.16k
xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) {
2137
8.16k
    xmlNodePtr cur;
2138
2139
8.16k
    if (name == NULL) {
2140
0
  return(NULL);
2141
0
    }
2142
2143
    /*
2144
     * Allocate a new node and fill the fields.
2145
     */
2146
8.16k
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2147
8.16k
    if (cur == NULL)
2148
0
  return(NULL);
2149
8.16k
    memset(cur, 0, sizeof(xmlNode));
2150
8.16k
    cur->type = XML_PI_NODE;
2151
8.16k
    cur->doc = doc;
2152
2153
8.16k
    if ((doc != NULL) && (doc->dict != NULL))
2154
7.49k
        cur->name = xmlDictLookup(doc->dict, name, -1);
2155
673
    else
2156
673
  cur->name = xmlStrdup(name);
2157
8.16k
    if (cur->name == NULL)
2158
0
        goto error;
2159
8.16k
    if (content != NULL) {
2160
3.30k
  cur->content = xmlStrdup(content);
2161
3.30k
        if (cur->content == NULL)
2162
0
            goto error;
2163
3.30k
    }
2164
2165
8.16k
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2166
0
  xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
2167
8.16k
    return(cur);
2168
2169
0
error:
2170
0
    xmlFreeNode(cur);
2171
0
    return(NULL);
2172
8.16k
}
2173
2174
/**
2175
 * xmlNewPI:
2176
 * @name:  the processing instruction name
2177
 * @content:  the PI content
2178
 *
2179
 * Creation of a processing instruction element.
2180
 *
2181
 * Use of this function is DISCOURAGED in favor of xmlNewDocPI.
2182
 *
2183
 * Returns a pointer to the new node object.
2184
 */
2185
xmlNodePtr
2186
0
xmlNewPI(const xmlChar *name, const xmlChar *content) {
2187
0
    return(xmlNewDocPI(NULL, name, content));
2188
0
}
2189
2190
/**
2191
 * xmlNewNode:
2192
 * @ns:  namespace if any
2193
 * @name:  the node name
2194
 *
2195
 * Creation of a new node element. @ns is optional (NULL).
2196
 *
2197
 * Use of this function is DISCOURAGED in favor of xmlNewDocNode.
2198
 *
2199
 * Returns a pointer to the new node object. Uses xmlStrdup() to make
2200
 * copy of @name.
2201
 */
2202
xmlNodePtr
2203
2.08k
xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
2204
2.08k
    xmlNodePtr cur;
2205
2206
2.08k
    if (name == NULL) {
2207
0
  return(NULL);
2208
0
    }
2209
2210
    /*
2211
     * Allocate a new node and fill the fields.
2212
     */
2213
2.08k
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2214
2.08k
    if (cur == NULL)
2215
0
  return(NULL);
2216
2.08k
    memset(cur, 0, sizeof(xmlNode));
2217
2.08k
    cur->type = XML_ELEMENT_NODE;
2218
2219
2.08k
    cur->name = xmlStrdup(name);
2220
2.08k
    if (cur->name == NULL)
2221
0
        goto error;
2222
2.08k
    cur->ns = ns;
2223
2224
2.08k
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2225
0
  xmlRegisterNodeDefaultValue(cur);
2226
2.08k
    return(cur);
2227
2228
0
error:
2229
0
    xmlFreeNode(cur);
2230
0
    return(NULL);
2231
2.08k
}
2232
2233
/**
2234
 * xmlNewNodeEatName:
2235
 * @ns:  namespace if any
2236
 * @name:  the node name
2237
 *
2238
 * Creation of a new node element. @ns is optional (NULL).
2239
 *
2240
 * Use of this function is DISCOURAGED in favor of xmlNewDocNodeEatName.
2241
 *
2242
 * Returns a pointer to the new node object, with pointer @name as
2243
 * new node's name. Use xmlNewNode() if a copy of @name string is
2244
 * is needed as new node's name.
2245
 */
2246
xmlNodePtr
2247
92.9k
xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) {
2248
92.9k
    xmlNodePtr cur;
2249
2250
92.9k
    if (name == NULL) {
2251
0
  return(NULL);
2252
0
    }
2253
2254
    /*
2255
     * Allocate a new node and fill the fields.
2256
     */
2257
92.9k
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2258
92.9k
    if (cur == NULL)
2259
0
  return(NULL);
2260
92.9k
    memset(cur, 0, sizeof(xmlNode));
2261
92.9k
    cur->type = XML_ELEMENT_NODE;
2262
2263
92.9k
    cur->name = name;
2264
92.9k
    cur->ns = ns;
2265
2266
92.9k
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2267
0
  xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
2268
92.9k
    return(cur);
2269
92.9k
}
2270
2271
/**
2272
 * xmlNewDocNode:
2273
 * @doc:  the document
2274
 * @ns:  namespace if any
2275
 * @name:  the node name
2276
 * @content:  the XML text content if any
2277
 *
2278
 * Creation of a new node element within a document. @ns and @content
2279
 * are optional (NULL).
2280
 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2281
 *       references, but XML special chars need to be escaped first by using
2282
 *       xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2283
 *       need entities support.
2284
 *
2285
 * Returns a pointer to the new node object.
2286
 */
2287
xmlNodePtr
2288
xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
2289
2.73k
              const xmlChar *name, const xmlChar *content) {
2290
2.73k
    xmlNodePtr cur;
2291
2292
2.73k
    if ((doc != NULL) && (doc->dict != NULL))
2293
647
        cur = xmlNewNodeEatName(ns, (xmlChar *)
2294
647
                          xmlDictLookup(doc->dict, name, -1));
2295
2.08k
    else
2296
2.08k
  cur = xmlNewNode(ns, name);
2297
2.73k
    if (cur != NULL) {
2298
2.73k
        cur->doc = doc;
2299
2.73k
  if (content != NULL) {
2300
0
      cur->children = xmlStringGetNodeList(doc, content);
2301
0
      UPDATE_LAST_CHILD_AND_PARENT(cur)
2302
0
  }
2303
2.73k
    }
2304
2305
2.73k
    return(cur);
2306
2.73k
}
2307
2308
/**
2309
 * xmlNewDocNodeEatName:
2310
 * @doc:  the document
2311
 * @ns:  namespace if any
2312
 * @name:  the node name
2313
 * @content:  the XML text content if any
2314
 *
2315
 * Creation of a new node element within a document. @ns and @content
2316
 * are optional (NULL).
2317
 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2318
 *       references, but XML special chars need to be escaped first by using
2319
 *       xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2320
 *       need entities support.
2321
 *
2322
 * Returns a pointer to the new node object.
2323
 */
2324
xmlNodePtr
2325
xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns,
2326
92.3k
              xmlChar *name, const xmlChar *content) {
2327
92.3k
    xmlNodePtr cur;
2328
2329
92.3k
    cur = xmlNewNodeEatName(ns, name);
2330
92.3k
    if (cur != NULL) {
2331
92.3k
        cur->doc = doc;
2332
92.3k
  if (content != NULL) {
2333
0
      cur->children = xmlStringGetNodeList(doc, content);
2334
0
            if (cur->children == NULL) {
2335
0
                xmlFreeNode(cur);
2336
0
                return(NULL);
2337
0
            }
2338
0
      UPDATE_LAST_CHILD_AND_PARENT(cur)
2339
0
  }
2340
92.3k
    } else {
2341
        /* if name don't come from the doc dictionary free it here */
2342
0
        if ((name != NULL) &&
2343
0
            ((doc == NULL) || (doc->dict == NULL) ||
2344
0
       (!(xmlDictOwns(doc->dict, name)))))
2345
0
      xmlFree(name);
2346
0
    }
2347
92.3k
    return(cur);
2348
92.3k
}
2349
2350
#ifdef LIBXML_TREE_ENABLED
2351
/**
2352
 * xmlNewDocRawNode:
2353
 * @doc:  the document
2354
 * @ns:  namespace if any
2355
 * @name:  the node name
2356
 * @content:  the text content if any
2357
 *
2358
 * Creation of a new node element within a document. @ns and @content
2359
 * are optional (NULL).
2360
 *
2361
 * Returns a pointer to the new node object.
2362
 */
2363
xmlNodePtr
2364
xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
2365
0
                 const xmlChar *name, const xmlChar *content) {
2366
0
    xmlNodePtr cur;
2367
2368
0
    cur = xmlNewDocNode(doc, ns, name, NULL);
2369
0
    if (cur != NULL) {
2370
0
        cur->doc = doc;
2371
0
  if (content != NULL) {
2372
0
      cur->children = xmlNewDocText(doc, content);
2373
0
      UPDATE_LAST_CHILD_AND_PARENT(cur)
2374
0
  }
2375
0
    }
2376
0
    return(cur);
2377
0
}
2378
2379
/**
2380
 * xmlNewDocFragment:
2381
 * @doc:  the document owning the fragment
2382
 *
2383
 * Creation of a new Fragment node.
2384
 * Returns a pointer to the new node object.
2385
 */
2386
xmlNodePtr
2387
0
xmlNewDocFragment(xmlDocPtr doc) {
2388
0
    xmlNodePtr cur;
2389
2390
    /*
2391
     * Allocate a new DocumentFragment node and fill the fields.
2392
     */
2393
0
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2394
0
    if (cur == NULL)
2395
0
  return(NULL);
2396
0
    memset(cur, 0, sizeof(xmlNode));
2397
0
    cur->type = XML_DOCUMENT_FRAG_NODE;
2398
2399
0
    cur->doc = doc;
2400
2401
0
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2402
0
  xmlRegisterNodeDefaultValue(cur);
2403
0
    return(cur);
2404
0
}
2405
#endif /* LIBXML_TREE_ENABLED */
2406
2407
/**
2408
 * xmlNewText:
2409
 * @content:  the text content
2410
 *
2411
 * Creation of a new text node.
2412
 *
2413
 * Use of this function is DISCOURAGED in favor of xmlNewDocText.
2414
 *
2415
 * Returns a pointer to the new node object.
2416
 */
2417
xmlNodePtr
2418
5.11k
xmlNewText(const xmlChar *content) {
2419
5.11k
    xmlNodePtr cur;
2420
2421
    /*
2422
     * Allocate a new node and fill the fields.
2423
     */
2424
5.11k
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2425
5.11k
    if (cur == NULL)
2426
0
  return(NULL);
2427
5.11k
    memset(cur, 0, sizeof(xmlNode));
2428
5.11k
    cur->type = XML_TEXT_NODE;
2429
2430
5.11k
    cur->name = xmlStringText;
2431
5.11k
    if (content != NULL) {
2432
23
  cur->content = xmlStrdup(content);
2433
23
        if (cur->content == NULL)
2434
0
            goto error;
2435
23
    }
2436
2437
5.11k
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2438
0
  xmlRegisterNodeDefaultValue(cur);
2439
5.11k
    return(cur);
2440
2441
0
error:
2442
0
    xmlFreeNode(cur);
2443
0
    return(NULL);
2444
5.11k
}
2445
2446
#ifdef LIBXML_TREE_ENABLED
2447
/**
2448
 * xmlNewTextChild:
2449
 * @parent:  the parent node
2450
 * @ns:  a namespace if any
2451
 * @name:  the name of the child
2452
 * @content:  the text content of the child if any.
2453
 *
2454
 * Creation of a new child element, added at the end of @parent children list.
2455
 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2456
 * created element inherits the namespace of @parent. If @content is non NULL,
2457
 * a child TEXT node will be created containing the string @content.
2458
 * NOTE: Use xmlNewChild() if @content will contain entities that need to be
2459
 * preserved. Use this function, xmlNewTextChild(), if you need to ensure that
2460
 * reserved XML chars that might appear in @content, such as the ampersand,
2461
 * greater-than or less-than signs, are automatically replaced by their XML
2462
 * escaped entity representations.
2463
 *
2464
 * Returns a pointer to the new node object.
2465
 */
2466
xmlNodePtr
2467
xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
2468
0
            const xmlChar *name, const xmlChar *content) {
2469
0
    xmlNodePtr cur, prev;
2470
2471
0
    if (parent == NULL) {
2472
0
  return(NULL);
2473
0
    }
2474
2475
0
    if (name == NULL) {
2476
0
  return(NULL);
2477
0
    }
2478
2479
    /*
2480
     * Allocate a new node
2481
     */
2482
0
    if (parent->type == XML_ELEMENT_NODE) {
2483
0
  if (ns == NULL)
2484
0
      cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
2485
0
  else
2486
0
      cur = xmlNewDocRawNode(parent->doc, ns, name, content);
2487
0
    } else if ((parent->type == XML_DOCUMENT_NODE) ||
2488
0
         (parent->type == XML_HTML_DOCUMENT_NODE)) {
2489
0
  if (ns == NULL)
2490
0
      cur = xmlNewDocRawNode((xmlDocPtr) parent, NULL, name, content);
2491
0
  else
2492
0
      cur = xmlNewDocRawNode((xmlDocPtr) parent, ns, name, content);
2493
0
    } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
2494
0
      cur = xmlNewDocRawNode( parent->doc, ns, name, content);
2495
0
    } else {
2496
0
  return(NULL);
2497
0
    }
2498
0
    if (cur == NULL) return(NULL);
2499
2500
    /*
2501
     * add the new element at the end of the children list.
2502
     */
2503
0
    cur->type = XML_ELEMENT_NODE;
2504
0
    cur->parent = parent;
2505
0
    cur->doc = parent->doc;
2506
0
    if (parent->children == NULL) {
2507
0
        parent->children = cur;
2508
0
  parent->last = cur;
2509
0
    } else {
2510
0
        prev = parent->last;
2511
0
  prev->next = cur;
2512
0
  cur->prev = prev;
2513
0
  parent->last = cur;
2514
0
    }
2515
2516
0
    return(cur);
2517
0
}
2518
#endif /* LIBXML_TREE_ENABLED */
2519
2520
/**
2521
 * xmlNewCharRef:
2522
 * @doc: the document
2523
 * @name:  the char ref string, starting with # or "&# ... ;"
2524
 *
2525
 * Creation of a new character reference node.
2526
 * Returns a pointer to the new node object.
2527
 */
2528
xmlNodePtr
2529
0
xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
2530
0
    xmlNodePtr cur;
2531
2532
0
    if (name == NULL)
2533
0
        return(NULL);
2534
2535
    /*
2536
     * Allocate a new node and fill the fields.
2537
     */
2538
0
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2539
0
    if (cur == NULL)
2540
0
  return(NULL);
2541
0
    memset(cur, 0, sizeof(xmlNode));
2542
0
    cur->type = XML_ENTITY_REF_NODE;
2543
2544
0
    cur->doc = doc;
2545
0
    if (name[0] == '&') {
2546
0
        int len;
2547
0
        name++;
2548
0
  len = xmlStrlen(name);
2549
0
  if (name[len - 1] == ';')
2550
0
      cur->name = xmlStrndup(name, len - 1);
2551
0
  else
2552
0
      cur->name = xmlStrndup(name, len);
2553
0
    } else
2554
0
  cur->name = xmlStrdup(name);
2555
0
    if (cur->name == NULL)
2556
0
        goto error;
2557
2558
0
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2559
0
  xmlRegisterNodeDefaultValue(cur);
2560
0
    return(cur);
2561
2562
0
error:
2563
0
    xmlFreeNode(cur);
2564
0
    return(NULL);
2565
0
}
2566
2567
/**
2568
 * xmlNewReference:
2569
 * @doc: the document
2570
 * @name:  the reference name, or the reference string with & and ;
2571
 *
2572
 * Creation of a new reference node.
2573
 * Returns a pointer to the new node object.
2574
 */
2575
xmlNodePtr
2576
4.87k
xmlNewReference(const xmlDoc *doc, const xmlChar *name) {
2577
4.87k
    xmlNodePtr cur;
2578
4.87k
    xmlEntityPtr ent;
2579
2580
4.87k
    if (name == NULL)
2581
0
        return(NULL);
2582
2583
    /*
2584
     * Allocate a new node and fill the fields.
2585
     */
2586
4.87k
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2587
4.87k
    if (cur == NULL)
2588
0
  return(NULL);
2589
4.87k
    memset(cur, 0, sizeof(xmlNode));
2590
4.87k
    cur->type = XML_ENTITY_REF_NODE;
2591
2592
4.87k
    cur->doc = (xmlDoc *)doc;
2593
4.87k
    if (name[0] == '&') {
2594
0
        int len;
2595
0
        name++;
2596
0
  len = xmlStrlen(name);
2597
0
  if (name[len - 1] == ';')
2598
0
      cur->name = xmlStrndup(name, len - 1);
2599
0
  else
2600
0
      cur->name = xmlStrndup(name, len);
2601
0
    } else
2602
4.87k
  cur->name = xmlStrdup(name);
2603
4.87k
    if (cur->name == NULL)
2604
0
        goto error;
2605
2606
4.87k
    ent = xmlGetDocEntity(doc, cur->name);
2607
4.87k
    if (ent != NULL) {
2608
3.26k
  cur->content = ent->content;
2609
  /*
2610
   * The parent pointer in entity is a DTD pointer and thus is NOT
2611
   * updated.  Not sure if this is 100% correct.
2612
   *  -George
2613
   */
2614
3.26k
  cur->children = (xmlNodePtr) ent;
2615
3.26k
  cur->last = (xmlNodePtr) ent;
2616
3.26k
    }
2617
2618
4.87k
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2619
0
  xmlRegisterNodeDefaultValue(cur);
2620
4.87k
    return(cur);
2621
2622
0
error:
2623
0
    xmlFreeNode(cur);
2624
0
    return(NULL);
2625
4.87k
}
2626
2627
/**
2628
 * xmlNewDocText:
2629
 * @doc: the document
2630
 * @content:  the text content
2631
 *
2632
 * Creation of a new text node within a document.
2633
 * Returns a pointer to the new node object.
2634
 */
2635
xmlNodePtr
2636
5.11k
xmlNewDocText(const xmlDoc *doc, const xmlChar *content) {
2637
5.11k
    xmlNodePtr cur;
2638
2639
5.11k
    cur = xmlNewText(content);
2640
5.11k
    if (cur != NULL) cur->doc = (xmlDoc *)doc;
2641
5.11k
    return(cur);
2642
5.11k
}
2643
2644
/**
2645
 * xmlNewTextLen:
2646
 * @content:  the text content
2647
 * @len:  the text len.
2648
 *
2649
 * Use of this function is DISCOURAGED in favor of xmlNewDocTextLen.
2650
 *
2651
 * Creation of a new text node with an extra parameter for the content's length
2652
 * Returns a pointer to the new node object.
2653
 */
2654
xmlNodePtr
2655
0
xmlNewTextLen(const xmlChar *content, int len) {
2656
0
    xmlNodePtr cur;
2657
2658
    /*
2659
     * Allocate a new node and fill the fields.
2660
     */
2661
0
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2662
0
    if (cur == NULL)
2663
0
  return(NULL);
2664
0
    memset(cur, 0, sizeof(xmlNode));
2665
0
    cur->type = XML_TEXT_NODE;
2666
2667
0
    cur->name = xmlStringText;
2668
0
    if (content != NULL) {
2669
0
  cur->content = xmlStrndup(content, len);
2670
0
    }
2671
2672
0
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2673
0
  xmlRegisterNodeDefaultValue(cur);
2674
0
    return(cur);
2675
0
}
2676
2677
/**
2678
 * xmlNewDocTextLen:
2679
 * @doc: the document
2680
 * @content:  the text content
2681
 * @len:  the text len.
2682
 *
2683
 * Creation of a new text node with an extra content length parameter. The
2684
 * text node pertain to a given document.
2685
 * Returns a pointer to the new node object.
2686
 */
2687
xmlNodePtr
2688
0
xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
2689
0
    xmlNodePtr cur;
2690
2691
0
    cur = xmlNewTextLen(content, len);
2692
0
    if (cur != NULL) cur->doc = doc;
2693
0
    return(cur);
2694
0
}
2695
2696
/**
2697
 * xmlNewComment:
2698
 * @content:  the comment content
2699
 *
2700
 * Use of this function is DISCOURAGED in favor of xmlNewDocComment.
2701
 *
2702
 * Creation of a new node containing a comment.
2703
 * Returns a pointer to the new node object.
2704
 */
2705
xmlNodePtr
2706
4.50k
xmlNewComment(const xmlChar *content) {
2707
4.50k
    xmlNodePtr cur;
2708
2709
    /*
2710
     * Allocate a new node and fill the fields.
2711
     */
2712
4.50k
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2713
4.50k
    if (cur == NULL)
2714
0
  return(NULL);
2715
4.50k
    memset(cur, 0, sizeof(xmlNode));
2716
4.50k
    cur->type = XML_COMMENT_NODE;
2717
2718
4.50k
    cur->name = xmlStringComment;
2719
4.50k
    if (content != NULL) {
2720
4.50k
  cur->content = xmlStrdup(content);
2721
4.50k
        if (cur->content == NULL)
2722
0
            goto error;
2723
4.50k
    }
2724
2725
4.50k
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2726
0
  xmlRegisterNodeDefaultValue(cur);
2727
4.50k
    return(cur);
2728
2729
0
error:
2730
0
    xmlFreeNode(cur);
2731
0
    return(NULL);
2732
4.50k
}
2733
2734
/**
2735
 * xmlNewCDataBlock:
2736
 * @doc:  the document
2737
 * @content:  the CDATA block content content
2738
 * @len:  the length of the block
2739
 *
2740
 * Creation of a new node containing a CDATA block.
2741
 * Returns a pointer to the new node object.
2742
 */
2743
xmlNodePtr
2744
505
xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
2745
505
    xmlNodePtr cur;
2746
2747
    /*
2748
     * Allocate a new node and fill the fields.
2749
     */
2750
505
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2751
505
    if (cur == NULL)
2752
0
  return(NULL);
2753
505
    memset(cur, 0, sizeof(xmlNode));
2754
505
    cur->type = XML_CDATA_SECTION_NODE;
2755
505
    cur->doc = doc;
2756
2757
505
    if (content != NULL) {
2758
505
  cur->content = xmlStrndup(content, len);
2759
505
        if (cur->content == NULL) {
2760
0
            xmlFree(cur);
2761
0
            return(NULL);
2762
0
        }
2763
505
    }
2764
2765
505
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2766
0
  xmlRegisterNodeDefaultValue(cur);
2767
505
    return(cur);
2768
505
}
2769
2770
/**
2771
 * xmlNewDocComment:
2772
 * @doc:  the document
2773
 * @content:  the comment content
2774
 *
2775
 * Creation of a new node containing a comment within a document.
2776
 * Returns a pointer to the new node object.
2777
 */
2778
xmlNodePtr
2779
4.50k
xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
2780
4.50k
    xmlNodePtr cur;
2781
2782
4.50k
    cur = xmlNewComment(content);
2783
4.50k
    if (cur != NULL) cur->doc = doc;
2784
4.50k
    return(cur);
2785
4.50k
}
2786
2787
0
static const xmlChar *_copyStringForNewDictIfNeeded(xmlDictPtr oldDict, xmlDictPtr newDict, const xmlChar *oldValue) {
2788
0
    const xmlChar *newValue = oldValue;
2789
0
    if (oldValue) {
2790
0
        int oldDictOwnsOldValue = oldDict && (xmlDictOwns(oldDict, oldValue) == 1);
2791
0
        if (oldDictOwnsOldValue) {
2792
0
            if (newDict)
2793
0
                newValue = xmlDictLookup(newDict, oldValue, -1);
2794
0
            else
2795
0
                newValue = xmlStrdup(oldValue);
2796
0
        }
2797
0
    }
2798
0
    return newValue;
2799
0
}
2800
2801
/**
2802
 * xmlSetTreeDoc:
2803
 * @tree:  the top element
2804
 * @doc:  the document
2805
 *
2806
 * update all nodes under the tree to point to the right document
2807
 */
2808
void
2809
0
xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) {
2810
0
    xmlAttrPtr prop;
2811
2812
0
    if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
2813
0
  return;
2814
0
    if (tree->doc != doc) {
2815
0
        xmlDictPtr oldTreeDict = tree->doc ? tree->doc->dict : NULL;
2816
0
        xmlDictPtr newDict = doc ? doc->dict : NULL;
2817
2818
0
  if(tree->type == XML_ELEMENT_NODE) {
2819
0
      prop = tree->properties;
2820
0
      while (prop != NULL) {
2821
0
                if (prop->atype == XML_ATTRIBUTE_ID) {
2822
0
                    xmlRemoveID(tree->doc, prop);
2823
0
                }
2824
2825
0
                if (prop->doc != doc) {
2826
0
                    xmlDictPtr oldPropDict = prop->doc ? prop->doc->dict : NULL;
2827
                    /* TODO: malloc check */
2828
0
                    prop->name = _copyStringForNewDictIfNeeded(oldPropDict, newDict, prop->name);
2829
0
                    prop->doc = doc;
2830
0
                }
2831
0
    xmlSetListDoc(prop->children, doc);
2832
2833
                /*
2834
                 * TODO: ID attributes should be also added to the new
2835
                 * document, but this breaks things like xmlReplaceNode.
2836
                 * The underlying problem is that xmlRemoveID is only called
2837
                 * if a node is destroyed, not if it's unlinked.
2838
                 */
2839
#if 0
2840
                if (xmlIsID(doc, tree, prop)) {
2841
                    xmlChar *idVal = xmlNodeListGetString(doc, prop->children,
2842
                                                          1);
2843
                    xmlAddID(NULL, doc, idVal, prop);
2844
                }
2845
#endif
2846
2847
0
    prop = prop->next;
2848
0
      }
2849
0
  }
2850
0
        if (tree->type == XML_ENTITY_REF_NODE) {
2851
            /*
2852
             * Clear 'children' which points to the entity declaration
2853
             * from the original document.
2854
             */
2855
0
            tree->children = NULL;
2856
0
        } else if (tree->children != NULL) {
2857
0
      xmlSetListDoc(tree->children, doc);
2858
0
        }
2859
2860
        /* TODO: malloc check */
2861
0
        tree->name = _copyStringForNewDictIfNeeded(oldTreeDict, newDict, tree->name);
2862
0
        tree->content = (xmlChar *)_copyStringForNewDictIfNeeded(oldTreeDict, NULL, tree->content);
2863
        /* FIXME: tree->ns should be updated as in xmlStaticCopyNode(). */
2864
0
  tree->doc = doc;
2865
0
    }
2866
0
}
2867
2868
/**
2869
 * xmlSetListDoc:
2870
 * @list:  the first element
2871
 * @doc:  the document
2872
 *
2873
 * update all nodes in the list to point to the right document
2874
 */
2875
void
2876
0
xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc) {
2877
0
    xmlNodePtr cur;
2878
2879
0
    if ((list == NULL) || (list->type == XML_NAMESPACE_DECL))
2880
0
  return;
2881
0
    cur = list;
2882
0
    while (cur != NULL) {
2883
0
  if (cur->doc != doc)
2884
0
      xmlSetTreeDoc(cur, doc);
2885
0
  cur = cur->next;
2886
0
    }
2887
0
}
2888
2889
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2890
/**
2891
 * xmlNewChild:
2892
 * @parent:  the parent node
2893
 * @ns:  a namespace if any
2894
 * @name:  the name of the child
2895
 * @content:  the XML content of the child if any.
2896
 *
2897
 * Creation of a new child element, added at the end of @parent children list.
2898
 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2899
 * created element inherits the namespace of @parent. If @content is non NULL,
2900
 * a child list containing the TEXTs and ENTITY_REFs node will be created.
2901
 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
2902
 *       references. XML special chars must be escaped first by using
2903
 *       xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used.
2904
 *
2905
 * Returns a pointer to the new node object.
2906
 */
2907
xmlNodePtr
2908
xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
2909
0
            const xmlChar *name, const xmlChar *content) {
2910
0
    xmlNodePtr cur, prev;
2911
2912
0
    if (parent == NULL) {
2913
0
  return(NULL);
2914
0
    }
2915
2916
0
    if (name == NULL) {
2917
0
  return(NULL);
2918
0
    }
2919
2920
    /*
2921
     * Allocate a new node
2922
     */
2923
0
    if (parent->type == XML_ELEMENT_NODE) {
2924
0
  if (ns == NULL)
2925
0
      cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
2926
0
  else
2927
0
      cur = xmlNewDocNode(parent->doc, ns, name, content);
2928
0
    } else if ((parent->type == XML_DOCUMENT_NODE) ||
2929
0
         (parent->type == XML_HTML_DOCUMENT_NODE)) {
2930
0
  if (ns == NULL)
2931
0
      cur = xmlNewDocNode((xmlDocPtr) parent, NULL, name, content);
2932
0
  else
2933
0
      cur = xmlNewDocNode((xmlDocPtr) parent, ns, name, content);
2934
0
    } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
2935
0
      cur = xmlNewDocNode( parent->doc, ns, name, content);
2936
0
    } else {
2937
0
  return(NULL);
2938
0
    }
2939
0
    if (cur == NULL) return(NULL);
2940
2941
    /*
2942
     * add the new element at the end of the children list.
2943
     */
2944
0
    cur->type = XML_ELEMENT_NODE;
2945
0
    cur->parent = parent;
2946
0
    cur->doc = parent->doc;
2947
0
    if (parent->children == NULL) {
2948
0
        parent->children = cur;
2949
0
  parent->last = cur;
2950
0
    } else {
2951
0
        prev = parent->last;
2952
0
  prev->next = cur;
2953
0
  cur->prev = prev;
2954
0
  parent->last = cur;
2955
0
    }
2956
2957
0
    return(cur);
2958
0
}
2959
#endif /* LIBXML_TREE_ENABLED */
2960
2961
/**
2962
 * xmlAddPropSibling:
2963
 * @prev:  the attribute to which @prop is added after
2964
 * @cur:   the base attribute passed to calling function
2965
 * @prop:  the new attribute
2966
 *
2967
 * Add a new attribute after @prev using @cur as base attribute.
2968
 * When inserting before @cur, @prev is passed as @cur->prev.
2969
 * When inserting after @cur, @prev is passed as @cur.
2970
 * If an existing attribute is found it is destroyed prior to adding @prop.
2971
 *
2972
 * See the note regarding namespaces in xmlAddChild.
2973
 *
2974
 * Returns the attribute being inserted or NULL in case of error.
2975
 */
2976
static xmlNodePtr
2977
0
xmlAddPropSibling(xmlNodePtr prev, xmlNodePtr cur, xmlNodePtr prop) {
2978
0
  xmlAttrPtr attr;
2979
2980
0
  if ((cur == NULL) || (cur->type != XML_ATTRIBUTE_NODE) ||
2981
0
      (prop == NULL) || (prop->type != XML_ATTRIBUTE_NODE) ||
2982
0
      ((prev != NULL) && (prev->type != XML_ATTRIBUTE_NODE)))
2983
0
    return(NULL);
2984
2985
  /* check if an attribute with the same name exists */
2986
0
  if (prop->ns == NULL)
2987
0
    attr = xmlHasNsProp(cur->parent, prop->name, NULL);
2988
0
  else
2989
0
    attr = xmlHasNsProp(cur->parent, prop->name, prop->ns->href);
2990
2991
0
  if (prop->doc != cur->doc) {
2992
0
    xmlSetTreeDoc(prop, cur->doc);
2993
0
  }
2994
0
  prop->parent = cur->parent;
2995
0
  prop->prev = prev;
2996
0
  if (prev != NULL) {
2997
0
    prop->next = prev->next;
2998
0
    prev->next = prop;
2999
0
    if (prop->next)
3000
0
      prop->next->prev = prop;
3001
0
  } else {
3002
0
    prop->next = cur;
3003
0
    cur->prev = prop;
3004
0
  }
3005
0
  if (prop->prev == NULL && prop->parent != NULL)
3006
0
    prop->parent->properties = (xmlAttrPtr) prop;
3007
0
  if ((attr != NULL) && (attr->type != XML_ATTRIBUTE_DECL)) {
3008
    /* different instance, destroy it (attributes must be unique) */
3009
0
    xmlRemoveProp((xmlAttrPtr) attr);
3010
0
  }
3011
0
  return prop;
3012
0
}
3013
3014
/**
3015
 * xmlAddNextSibling:
3016
 * @cur:  the child node
3017
 * @elem:  the new node
3018
 *
3019
 * Add a new node @elem as the next sibling of @cur
3020
 * If the new node was already inserted in a document it is
3021
 * first unlinked from its existing context.
3022
 * As a result of text merging @elem may be freed.
3023
 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3024
 * If there is an attribute with equal name, it is first destroyed.
3025
 *
3026
 * See the note regarding namespaces in xmlAddChild.
3027
 *
3028
 * Returns the new node or NULL in case of error.
3029
 */
3030
xmlNodePtr
3031
3.08k
xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
3032
3.08k
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3033
0
  return(NULL);
3034
0
    }
3035
3.08k
    if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
3036
0
  return(NULL);
3037
0
    }
3038
3039
3.08k
    if (cur == elem) {
3040
0
  return(NULL);
3041
0
    }
3042
3043
3.08k
    xmlUnlinkNode(elem);
3044
3045
3.08k
    if (elem->type == XML_TEXT_NODE) {
3046
774
  if (cur->type == XML_TEXT_NODE) {
3047
0
      xmlNodeAddContent(cur, elem->content);
3048
0
      xmlFreeNode(elem);
3049
0
      return(cur);
3050
0
  }
3051
774
  if ((cur->next != NULL) && (cur->next->type == XML_TEXT_NODE) &&
3052
774
            (cur->name == cur->next->name)) {
3053
0
      xmlChar *tmp;
3054
3055
            /* TODO: malloc check */
3056
0
      tmp = xmlStrdup(elem->content);
3057
0
      tmp = xmlStrcat(tmp, cur->next->content);
3058
0
      xmlNodeSetContent(cur->next, tmp);
3059
0
      xmlFree(tmp);
3060
0
      xmlFreeNode(elem);
3061
0
      return(cur->next);
3062
0
  }
3063
2.31k
    } else if (elem->type == XML_ATTRIBUTE_NODE) {
3064
0
    return xmlAddPropSibling(cur, cur, elem);
3065
0
    }
3066
3067
3.08k
    if (elem->doc != cur->doc) {
3068
0
  xmlSetTreeDoc(elem, cur->doc);
3069
0
    }
3070
3.08k
    elem->parent = cur->parent;
3071
3.08k
    elem->prev = cur;
3072
3.08k
    elem->next = cur->next;
3073
3.08k
    cur->next = elem;
3074
3.08k
    if (elem->next != NULL)
3075
0
  elem->next->prev = elem;
3076
3.08k
    if ((elem->parent != NULL) && (elem->parent->last == cur))
3077
0
  elem->parent->last = elem;
3078
3.08k
    return(elem);
3079
3.08k
}
3080
3081
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
3082
    defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
3083
/**
3084
 * xmlAddPrevSibling:
3085
 * @cur:  the child node
3086
 * @elem:  the new node
3087
 *
3088
 * Add a new node @elem as the previous sibling of @cur
3089
 * merging adjacent TEXT nodes (@elem may be freed)
3090
 * If the new node was already inserted in a document it is
3091
 * first unlinked from its existing context.
3092
 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3093
 * If there is an attribute with equal name, it is first destroyed.
3094
 *
3095
 * See the note regarding namespaces in xmlAddChild.
3096
 *
3097
 * Returns the new node or NULL in case of error.
3098
 */
3099
xmlNodePtr
3100
0
xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
3101
0
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3102
0
  return(NULL);
3103
0
    }
3104
0
    if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
3105
0
  return(NULL);
3106
0
    }
3107
3108
0
    if (cur == elem) {
3109
0
  return(NULL);
3110
0
    }
3111
3112
0
    xmlUnlinkNode(elem);
3113
3114
0
    if (elem->type == XML_TEXT_NODE) {
3115
0
  if (cur->type == XML_TEXT_NODE) {
3116
0
      xmlChar *tmp;
3117
3118
            /* TODO: malloc check */
3119
0
      tmp = xmlStrdup(elem->content);
3120
0
      tmp = xmlStrcat(tmp, cur->content);
3121
0
      xmlNodeSetContent(cur, tmp);
3122
0
      xmlFree(tmp);
3123
0
      xmlFreeNode(elem);
3124
0
      return(cur);
3125
0
  }
3126
0
  if ((cur->prev != NULL) && (cur->prev->type == XML_TEXT_NODE) &&
3127
0
            (cur->name == cur->prev->name)) {
3128
0
      xmlNodeAddContent(cur->prev, elem->content);
3129
0
      xmlFreeNode(elem);
3130
0
      return(cur->prev);
3131
0
  }
3132
0
    } else if (elem->type == XML_ATTRIBUTE_NODE) {
3133
0
    return xmlAddPropSibling(cur->prev, cur, elem);
3134
0
    }
3135
3136
0
    if (elem->doc != cur->doc) {
3137
0
  xmlSetTreeDoc(elem, cur->doc);
3138
0
    }
3139
0
    elem->parent = cur->parent;
3140
0
    elem->next = cur;
3141
0
    elem->prev = cur->prev;
3142
0
    cur->prev = elem;
3143
0
    if (elem->prev != NULL)
3144
0
  elem->prev->next = elem;
3145
0
    if ((elem->parent != NULL) && (elem->parent->children == cur)) {
3146
0
    elem->parent->children = elem;
3147
0
    }
3148
0
    return(elem);
3149
0
}
3150
#endif /* LIBXML_TREE_ENABLED */
3151
3152
/**
3153
 * xmlAddSibling:
3154
 * @cur:  the child node
3155
 * @elem:  the new node
3156
 *
3157
 * Add a new element @elem to the list of siblings of @cur
3158
 * merging adjacent TEXT nodes (@elem may be freed)
3159
 * If the new element was already inserted in a document it is
3160
 * first unlinked from its existing context.
3161
 *
3162
 * See the note regarding namespaces in xmlAddChild.
3163
 *
3164
 * Returns the new element or NULL in case of error.
3165
 */
3166
xmlNodePtr
3167
0
xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
3168
0
    xmlNodePtr parent;
3169
3170
0
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3171
0
  return(NULL);
3172
0
    }
3173
3174
0
    if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
3175
0
  return(NULL);
3176
0
    }
3177
3178
0
    if (cur == elem) {
3179
0
  return(NULL);
3180
0
    }
3181
3182
    /*
3183
     * Constant time is we can rely on the ->parent->last to find
3184
     * the last sibling.
3185
     */
3186
0
    if ((cur->type != XML_ATTRIBUTE_NODE) && (cur->parent != NULL) &&
3187
0
  (cur->parent->children != NULL) &&
3188
0
  (cur->parent->last != NULL) &&
3189
0
  (cur->parent->last->next == NULL)) {
3190
0
  cur = cur->parent->last;
3191
0
    } else {
3192
0
  while (cur->next != NULL) cur = cur->next;
3193
0
    }
3194
3195
0
    xmlUnlinkNode(elem);
3196
3197
0
    if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE) &&
3198
0
        (cur->name == elem->name)) {
3199
0
  xmlNodeAddContent(cur, elem->content);
3200
0
  xmlFreeNode(elem);
3201
0
  return(cur);
3202
0
    } else if (elem->type == XML_ATTRIBUTE_NODE) {
3203
0
    return xmlAddPropSibling(cur, cur, elem);
3204
0
    }
3205
3206
0
    if (elem->doc != cur->doc) {
3207
0
  xmlSetTreeDoc(elem, cur->doc);
3208
0
    }
3209
0
    parent = cur->parent;
3210
0
    elem->prev = cur;
3211
0
    elem->next = NULL;
3212
0
    elem->parent = parent;
3213
0
    cur->next = elem;
3214
0
    if (parent != NULL)
3215
0
  parent->last = elem;
3216
3217
0
    return(elem);
3218
0
}
3219
3220
/**
3221
 * xmlAddChildList:
3222
 * @parent:  the parent node
3223
 * @cur:  the first node in the list
3224
 *
3225
 * Add a list of node at the end of the child list of the parent
3226
 * merging adjacent TEXT nodes (@cur may be freed)
3227
 *
3228
 * See the note regarding namespaces in xmlAddChild.
3229
 *
3230
 * Returns the last child or NULL in case of error.
3231
 */
3232
xmlNodePtr
3233
0
xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
3234
0
    xmlNodePtr prev;
3235
3236
0
    if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
3237
0
  return(NULL);
3238
0
    }
3239
3240
0
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3241
0
  return(NULL);
3242
0
    }
3243
3244
0
    if ((cur->doc != NULL) && (parent->doc != NULL) &&
3245
0
        (cur->doc != parent->doc)) {
3246
0
    }
3247
3248
    /*
3249
     * add the first element at the end of the children list.
3250
     */
3251
3252
0
    if (parent->children == NULL) {
3253
0
        parent->children = cur;
3254
0
    } else {
3255
  /*
3256
   * If cur and parent->last both are TEXT nodes, then merge them.
3257
   */
3258
0
  if ((cur->type == XML_TEXT_NODE) &&
3259
0
      (parent->last->type == XML_TEXT_NODE) &&
3260
0
      (cur->name == parent->last->name)) {
3261
0
      xmlNodeAddContent(parent->last, cur->content);
3262
      /*
3263
       * if it's the only child, nothing more to be done.
3264
       */
3265
0
      if (cur->next == NULL) {
3266
0
    xmlFreeNode(cur);
3267
0
    return(parent->last);
3268
0
      }
3269
0
      prev = cur;
3270
0
      cur = cur->next;
3271
0
      xmlFreeNode(prev);
3272
0
  }
3273
0
        prev = parent->last;
3274
0
  prev->next = cur;
3275
0
  cur->prev = prev;
3276
0
    }
3277
0
    while (cur->next != NULL) {
3278
0
  cur->parent = parent;
3279
0
  if (cur->doc != parent->doc) {
3280
0
      xmlSetTreeDoc(cur, parent->doc);
3281
0
  }
3282
0
        cur = cur->next;
3283
0
    }
3284
0
    cur->parent = parent;
3285
    /* the parent may not be linked to a doc ! */
3286
0
    if (cur->doc != parent->doc) {
3287
0
        xmlSetTreeDoc(cur, parent->doc);
3288
0
    }
3289
0
    parent->last = cur;
3290
3291
0
    return(cur);
3292
0
}
3293
3294
/**
3295
 * xmlAddChild:
3296
 * @parent:  the parent node
3297
 * @cur:  the child node
3298
 *
3299
 * Add a new node to @parent, at the end of the child (or property) list
3300
 * merging adjacent TEXT nodes (in which case @cur is freed)
3301
 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3302
 * If there is an attribute with equal name, it is first destroyed.
3303
 *
3304
 * All tree manipulation functions can safely move nodes within a document.
3305
 * But when moving nodes from one document to another, references to
3306
 * namespaces in element or attribute nodes are NOT fixed. In this case,
3307
 * you MUST call xmlReconciliateNs after the move operation to avoid
3308
 * memory errors.
3309
 *
3310
 * Returns the child or NULL in case of error.
3311
 */
3312
xmlNodePtr
3313
122k
xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
3314
122k
    xmlNodePtr prev;
3315
3316
122k
    if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
3317
194
  return(NULL);
3318
194
    }
3319
3320
121k
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3321
0
  return(NULL);
3322
0
    }
3323
3324
121k
    if (parent == cur) {
3325
0
  return(NULL);
3326
0
    }
3327
    /*
3328
     * If cur is a TEXT node, merge its content with adjacent TEXT nodes
3329
     * cur is then freed.
3330
     */
3331
121k
    if (cur->type == XML_TEXT_NODE) {
3332
12.5k
  if ((parent->type == XML_TEXT_NODE) &&
3333
12.5k
      (parent->content != NULL) &&
3334
12.5k
      (parent->name == cur->name)) {
3335
0
      if (xmlNodeAddContent(parent, cur->content) != 0) {
3336
0
                xmlFreeNode(cur);
3337
0
                return(NULL);
3338
0
            }
3339
0
      xmlFreeNode(cur);
3340
0
      return(parent);
3341
0
  }
3342
12.5k
  if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) &&
3343
12.5k
      (parent->last->name == cur->name) &&
3344
12.5k
      (parent->last != cur)) {
3345
0
      if (xmlNodeAddContent(parent->last, cur->content) != 0) {
3346
0
                xmlFreeNode(cur);
3347
0
                return(NULL);
3348
0
            }
3349
0
      xmlFreeNode(cur);
3350
0
      return(parent->last);
3351
0
  }
3352
12.5k
    }
3353
3354
    /*
3355
     * add the new element at the end of the children list.
3356
     */
3357
121k
    prev = cur->parent;
3358
121k
    cur->parent = parent;
3359
121k
    if (cur->doc != parent->doc) {
3360
0
  xmlSetTreeDoc(cur, parent->doc);
3361
0
    }
3362
    /* this check prevents a loop on tree-traversions if a developer
3363
     * tries to add a node to its parent multiple times
3364
     */
3365
121k
    if (prev == parent)
3366
0
  return(cur);
3367
3368
    /*
3369
     * Coalescing
3370
     */
3371
121k
    if ((parent->type == XML_TEXT_NODE) &&
3372
121k
  (parent->content != NULL) &&
3373
121k
  (parent != cur)) {
3374
0
  if (xmlNodeAddContent(parent, cur->content) != 0) {
3375
0
            xmlFreeNode(cur);
3376
0
            return(NULL);
3377
0
        }
3378
0
  xmlFreeNode(cur);
3379
0
  return(parent);
3380
0
    }
3381
121k
    if (cur->type == XML_ATTRIBUTE_NODE) {
3382
0
    if (parent->type != XML_ELEMENT_NODE)
3383
0
      return(NULL);
3384
0
  if (parent->properties != NULL) {
3385
      /* check if an attribute with the same name exists */
3386
0
      xmlAttrPtr lastattr;
3387
3388
0
      if (cur->ns == NULL)
3389
0
    lastattr = xmlHasNsProp(parent, cur->name, NULL);
3390
0
      else
3391
0
    lastattr = xmlHasNsProp(parent, cur->name, cur->ns->href);
3392
0
      if ((lastattr != NULL) && (lastattr != (xmlAttrPtr) cur) && (lastattr->type != XML_ATTRIBUTE_DECL)) {
3393
    /* different instance, destroy it (attributes must be unique) */
3394
0
      xmlUnlinkNode((xmlNodePtr) lastattr);
3395
0
    xmlFreeProp(lastattr);
3396
0
      }
3397
0
    if (lastattr == (xmlAttrPtr) cur)
3398
0
      return(cur);
3399
3400
0
  }
3401
0
  if (parent->properties == NULL) {
3402
0
      parent->properties = (xmlAttrPtr) cur;
3403
0
  } else {
3404
      /* find the end */
3405
0
      xmlAttrPtr lastattr = parent->properties;
3406
0
      while (lastattr->next != NULL) {
3407
0
    lastattr = lastattr->next;
3408
0
      }
3409
0
      lastattr->next = (xmlAttrPtr) cur;
3410
0
      ((xmlAttrPtr) cur)->prev = lastattr;
3411
0
  }
3412
121k
    } else {
3413
121k
  if (parent->children == NULL) {
3414
15.4k
      parent->children = cur;
3415
15.4k
      parent->last = cur;
3416
106k
  } else {
3417
106k
      prev = parent->last;
3418
106k
      prev->next = cur;
3419
106k
      cur->prev = prev;
3420
106k
      parent->last = cur;
3421
106k
  }
3422
121k
    }
3423
121k
    return(cur);
3424
121k
}
3425
3426
/**
3427
 * xmlGetLastChild:
3428
 * @parent:  the parent node
3429
 *
3430
 * Search the last child of a node.
3431
 * Returns the last child or NULL if none.
3432
 */
3433
xmlNodePtr
3434
2.18k
xmlGetLastChild(const xmlNode *parent) {
3435
2.18k
    if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
3436
0
  return(NULL);
3437
0
    }
3438
2.18k
    return(parent->last);
3439
2.18k
}
3440
3441
#ifdef LIBXML_TREE_ENABLED
3442
/*
3443
 * 5 interfaces from DOM ElementTraversal
3444
 */
3445
3446
/**
3447
 * xmlChildElementCount:
3448
 * @parent: the parent node
3449
 *
3450
 * Finds the current number of child nodes of that element which are
3451
 * element nodes.
3452
 * Note the handling of entities references is different than in
3453
 * the W3C DOM element traversal spec since we don't have back reference
3454
 * from entities content to entities references.
3455
 *
3456
 * Returns the count of element child or 0 if not available
3457
 */
3458
unsigned long
3459
0
xmlChildElementCount(xmlNodePtr parent) {
3460
0
    unsigned long ret = 0;
3461
0
    xmlNodePtr cur = NULL;
3462
3463
0
    if (parent == NULL)
3464
0
        return(0);
3465
0
    switch (parent->type) {
3466
0
        case XML_ELEMENT_NODE:
3467
0
        case XML_ENTITY_NODE:
3468
0
        case XML_DOCUMENT_NODE:
3469
0
        case XML_DOCUMENT_FRAG_NODE:
3470
0
        case XML_HTML_DOCUMENT_NODE:
3471
0
            cur = parent->children;
3472
0
            break;
3473
0
        default:
3474
0
            return(0);
3475
0
    }
3476
0
    while (cur != NULL) {
3477
0
        if (cur->type == XML_ELEMENT_NODE)
3478
0
            ret++;
3479
0
        cur = cur->next;
3480
0
    }
3481
0
    return(ret);
3482
0
}
3483
3484
/**
3485
 * xmlFirstElementChild:
3486
 * @parent: the parent node
3487
 *
3488
 * Finds the first child node of that element which is a Element node
3489
 * Note the handling of entities references is different than in
3490
 * the W3C DOM element traversal spec since we don't have back reference
3491
 * from entities content to entities references.
3492
 *
3493
 * Returns the first element child or NULL if not available
3494
 */
3495
xmlNodePtr
3496
0
xmlFirstElementChild(xmlNodePtr parent) {
3497
0
    xmlNodePtr cur = NULL;
3498
3499
0
    if (parent == NULL)
3500
0
        return(NULL);
3501
0
    switch (parent->type) {
3502
0
        case XML_ELEMENT_NODE:
3503
0
        case XML_ENTITY_NODE:
3504
0
        case XML_DOCUMENT_NODE:
3505
0
        case XML_DOCUMENT_FRAG_NODE:
3506
0
        case XML_HTML_DOCUMENT_NODE:
3507
0
            cur = parent->children;
3508
0
            break;
3509
0
        default:
3510
0
            return(NULL);
3511
0
    }
3512
0
    while (cur != NULL) {
3513
0
        if (cur->type == XML_ELEMENT_NODE)
3514
0
            return(cur);
3515
0
        cur = cur->next;
3516
0
    }
3517
0
    return(NULL);
3518
0
}
3519
3520
/**
3521
 * xmlLastElementChild:
3522
 * @parent: the parent node
3523
 *
3524
 * Finds the last child node of that element which is a Element node
3525
 * Note the handling of entities references is different than in
3526
 * the W3C DOM element traversal spec since we don't have back reference
3527
 * from entities content to entities references.
3528
 *
3529
 * Returns the last element child or NULL if not available
3530
 */
3531
xmlNodePtr
3532
0
xmlLastElementChild(xmlNodePtr parent) {
3533
0
    xmlNodePtr cur = NULL;
3534
3535
0
    if (parent == NULL)
3536
0
        return(NULL);
3537
0
    switch (parent->type) {
3538
0
        case XML_ELEMENT_NODE:
3539
0
        case XML_ENTITY_NODE:
3540
0
        case XML_DOCUMENT_NODE:
3541
0
        case XML_DOCUMENT_FRAG_NODE:
3542
0
        case XML_HTML_DOCUMENT_NODE:
3543
0
            cur = parent->last;
3544
0
            break;
3545
0
        default:
3546
0
            return(NULL);
3547
0
    }
3548
0
    while (cur != NULL) {
3549
0
        if (cur->type == XML_ELEMENT_NODE)
3550
0
            return(cur);
3551
0
        cur = cur->prev;
3552
0
    }
3553
0
    return(NULL);
3554
0
}
3555
3556
/**
3557
 * xmlPreviousElementSibling:
3558
 * @node: the current node
3559
 *
3560
 * Finds the first closest previous sibling of the node which is an
3561
 * element node.
3562
 * Note the handling of entities references is different than in
3563
 * the W3C DOM element traversal spec since we don't have back reference
3564
 * from entities content to entities references.
3565
 *
3566
 * Returns the previous element sibling or NULL if not available
3567
 */
3568
xmlNodePtr
3569
0
xmlPreviousElementSibling(xmlNodePtr node) {
3570
0
    if (node == NULL)
3571
0
        return(NULL);
3572
0
    switch (node->type) {
3573
0
        case XML_ELEMENT_NODE:
3574
0
        case XML_TEXT_NODE:
3575
0
        case XML_CDATA_SECTION_NODE:
3576
0
        case XML_ENTITY_REF_NODE:
3577
0
        case XML_ENTITY_NODE:
3578
0
        case XML_PI_NODE:
3579
0
        case XML_COMMENT_NODE:
3580
0
        case XML_XINCLUDE_START:
3581
0
        case XML_XINCLUDE_END:
3582
0
            node = node->prev;
3583
0
            break;
3584
0
        default:
3585
0
            return(NULL);
3586
0
    }
3587
0
    while (node != NULL) {
3588
0
        if (node->type == XML_ELEMENT_NODE)
3589
0
            return(node);
3590
0
        node = node->prev;
3591
0
    }
3592
0
    return(NULL);
3593
0
}
3594
3595
/**
3596
 * xmlNextElementSibling:
3597
 * @node: the current node
3598
 *
3599
 * Finds the first closest next sibling of the node which is an
3600
 * element node.
3601
 * Note the handling of entities references is different than in
3602
 * the W3C DOM element traversal spec since we don't have back reference
3603
 * from entities content to entities references.
3604
 *
3605
 * Returns the next element sibling or NULL if not available
3606
 */
3607
xmlNodePtr
3608
0
xmlNextElementSibling(xmlNodePtr node) {
3609
0
    if (node == NULL)
3610
0
        return(NULL);
3611
0
    switch (node->type) {
3612
0
        case XML_ELEMENT_NODE:
3613
0
        case XML_TEXT_NODE:
3614
0
        case XML_CDATA_SECTION_NODE:
3615
0
        case XML_ENTITY_REF_NODE:
3616
0
        case XML_ENTITY_NODE:
3617
0
        case XML_PI_NODE:
3618
0
        case XML_COMMENT_NODE:
3619
0
        case XML_DTD_NODE:
3620
0
        case XML_XINCLUDE_START:
3621
0
        case XML_XINCLUDE_END:
3622
0
            node = node->next;
3623
0
            break;
3624
0
        default:
3625
0
            return(NULL);
3626
0
    }
3627
0
    while (node != NULL) {
3628
0
        if (node->type == XML_ELEMENT_NODE)
3629
0
            return(node);
3630
0
        node = node->next;
3631
0
    }
3632
0
    return(NULL);
3633
0
}
3634
3635
#endif /* LIBXML_TREE_ENABLED */
3636
3637
/**
3638
 * xmlFreeNodeList:
3639
 * @cur:  the first node in the list
3640
 *
3641
 * Free a node and all its siblings, this is a recursive behaviour, all
3642
 * the children are freed too.
3643
 */
3644
void
3645
20.2k
xmlFreeNodeList(xmlNodePtr cur) {
3646
20.2k
    xmlNodePtr next;
3647
20.2k
    xmlNodePtr parent;
3648
20.2k
    xmlDictPtr dict = NULL;
3649
20.2k
    size_t depth = 0;
3650
3651
20.2k
    if (cur == NULL) return;
3652
19.8k
    if (cur->type == XML_NAMESPACE_DECL) {
3653
0
  xmlFreeNsList((xmlNsPtr) cur);
3654
0
  return;
3655
0
    }
3656
19.8k
    if (cur->doc != NULL) dict = cur->doc->dict;
3657
133k
    while (1) {
3658
150k
        while ((cur->children != NULL) &&
3659
150k
               (cur->type != XML_DOCUMENT_NODE) &&
3660
150k
               (cur->type != XML_HTML_DOCUMENT_NODE) &&
3661
150k
               (cur->type != XML_DTD_NODE) &&
3662
150k
               (cur->type != XML_ENTITY_REF_NODE)) {
3663
17.3k
            cur = cur->children;
3664
17.3k
            depth += 1;
3665
17.3k
        }
3666
3667
133k
        next = cur->next;
3668
133k
        parent = cur->parent;
3669
133k
  if ((cur->type == XML_DOCUMENT_NODE) ||
3670
133k
            (cur->type == XML_HTML_DOCUMENT_NODE)) {
3671
0
            xmlFreeDoc((xmlDocPtr) cur);
3672
133k
        } else if (cur->type != XML_DTD_NODE) {
3673
3674
133k
      if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
3675
0
    xmlDeregisterNodeDefaultValue(cur);
3676
3677
133k
      if (((cur->type == XML_ELEMENT_NODE) ||
3678
133k
     (cur->type == XML_XINCLUDE_START) ||
3679
133k
     (cur->type == XML_XINCLUDE_END)) &&
3680
133k
    (cur->properties != NULL))
3681
7.76k
    xmlFreePropList(cur->properties);
3682
133k
      if ((cur->type != XML_ELEMENT_NODE) &&
3683
133k
    (cur->type != XML_XINCLUDE_START) &&
3684
133k
    (cur->type != XML_XINCLUDE_END) &&
3685
133k
    (cur->type != XML_ENTITY_REF_NODE) &&
3686
133k
    (cur->content != (xmlChar *) &(cur->properties))) {
3687
33.7k
    DICT_FREE(cur->content)
3688
33.7k
      }
3689
133k
      if (((cur->type == XML_ELEMENT_NODE) ||
3690
133k
           (cur->type == XML_XINCLUDE_START) ||
3691
133k
     (cur->type == XML_XINCLUDE_END)) &&
3692
133k
    (cur->nsDef != NULL))
3693
50.3k
    xmlFreeNsList(cur->nsDef);
3694
3695
      /*
3696
       * When a node is a text node or a comment, it uses a global static
3697
       * variable for the name of the node.
3698
       * Otherwise the node name might come from the document's
3699
       * dictionary
3700
       */
3701
133k
      if ((cur->name != NULL) &&
3702
133k
    (cur->type != XML_TEXT_NODE) &&
3703
133k
    (cur->type != XML_COMMENT_NODE))
3704
100k
    DICT_FREE(cur->name)
3705
133k
      xmlFree(cur);
3706
133k
  }
3707
3708
133k
        if (next != NULL) {
3709
96.0k
      cur = next;
3710
96.0k
        } else {
3711
37.1k
            if ((depth == 0) || (parent == NULL))
3712
19.8k
                break;
3713
17.3k
            depth -= 1;
3714
17.3k
            cur = parent;
3715
17.3k
            cur->children = NULL;
3716
17.3k
        }
3717
133k
    }
3718
19.8k
}
3719
3720
/**
3721
 * xmlFreeNode:
3722
 * @cur:  the node
3723
 *
3724
 * Free a node, this is a recursive behaviour, all the children are freed too.
3725
 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
3726
 */
3727
void
3728
11.0k
xmlFreeNode(xmlNodePtr cur) {
3729
11.0k
    xmlDictPtr dict = NULL;
3730
3731
11.0k
    if (cur == NULL) return;
3732
3733
    /* use xmlFreeDtd for DTD nodes */
3734
11.0k
    if (cur->type == XML_DTD_NODE) {
3735
0
  xmlFreeDtd((xmlDtdPtr) cur);
3736
0
  return;
3737
0
    }
3738
11.0k
    if (cur->type == XML_NAMESPACE_DECL) {
3739
0
  xmlFreeNs((xmlNsPtr) cur);
3740
0
        return;
3741
0
    }
3742
11.0k
    if (cur->type == XML_ATTRIBUTE_NODE) {
3743
0
  xmlFreeProp((xmlAttrPtr) cur);
3744
0
  return;
3745
0
    }
3746
3747
11.0k
    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
3748
0
  xmlDeregisterNodeDefaultValue(cur);
3749
3750
11.0k
    if (cur->doc != NULL) dict = cur->doc->dict;
3751
3752
11.0k
    if (cur->type == XML_ENTITY_DECL) {
3753
0
        xmlEntityPtr ent = (xmlEntityPtr) cur;
3754
0
  DICT_FREE(ent->SystemID);
3755
0
  DICT_FREE(ent->ExternalID);
3756
0
    }
3757
11.0k
    if ((cur->children != NULL) &&
3758
11.0k
  (cur->type != XML_ENTITY_REF_NODE))
3759
140
  xmlFreeNodeList(cur->children);
3760
3761
11.0k
    if ((cur->type == XML_ELEMENT_NODE) ||
3762
11.0k
        (cur->type == XML_XINCLUDE_START) ||
3763
11.0k
        (cur->type == XML_XINCLUDE_END)) {
3764
716
        if (cur->properties != NULL)
3765
0
            xmlFreePropList(cur->properties);
3766
716
        if (cur->nsDef != NULL)
3767
0
            xmlFreeNsList(cur->nsDef);
3768
10.3k
    } else if ((cur->content != NULL) &&
3769
10.3k
               (cur->type != XML_ENTITY_REF_NODE) &&
3770
10.3k
               (cur->content != (xmlChar *) &(cur->properties))) {
3771
6.53k
        DICT_FREE(cur->content)
3772
6.53k
    }
3773
3774
    /*
3775
     * When a node is a text node or a comment, it uses a global static
3776
     * variable for the name of the node.
3777
     * Otherwise the node name might come from the document's dictionary
3778
     */
3779
11.0k
    if ((cur->name != NULL) &&
3780
11.0k
        (cur->type != XML_TEXT_NODE) &&
3781
11.0k
        (cur->type != XML_COMMENT_NODE))
3782
7.47k
  DICT_FREE(cur->name)
3783
3784
11.0k
    xmlFree(cur);
3785
11.0k
}
3786
3787
/**
3788
 * xmlUnlinkNode:
3789
 * @cur:  the node
3790
 *
3791
 * Unlink a node from it's current context, the node is not freed
3792
 * If one need to free the node, use xmlFreeNode() routine after the
3793
 * unlink to discard it.
3794
 * Note that namespace nodes can't be unlinked as they do not have
3795
 * pointer to their parent.
3796
 */
3797
void
3798
58.5k
xmlUnlinkNode(xmlNodePtr cur) {
3799
58.5k
    if (cur == NULL) {
3800
0
  return;
3801
0
    }
3802
58.5k
    if (cur->type == XML_NAMESPACE_DECL)
3803
0
        return;
3804
58.5k
    if (cur->type == XML_DTD_NODE) {
3805
7.76k
  xmlDocPtr doc;
3806
7.76k
  doc = cur->doc;
3807
7.76k
  if (doc != NULL) {
3808
7.76k
      if (doc->intSubset == (xmlDtdPtr) cur)
3809
7.76k
    doc->intSubset = NULL;
3810
7.76k
      if (doc->extSubset == (xmlDtdPtr) cur)
3811
137
    doc->extSubset = NULL;
3812
7.76k
  }
3813
7.76k
    }
3814
58.5k
    if (cur->type == XML_ENTITY_DECL) {
3815
0
        xmlDocPtr doc;
3816
0
  doc = cur->doc;
3817
0
  if (doc != NULL) {
3818
0
      if (doc->intSubset != NULL) {
3819
0
          if (xmlHashLookup(doc->intSubset->entities, cur->name) == cur)
3820
0
        xmlHashRemoveEntry(doc->intSubset->entities, cur->name,
3821
0
                           NULL);
3822
0
          if (xmlHashLookup(doc->intSubset->pentities, cur->name) == cur)
3823
0
        xmlHashRemoveEntry(doc->intSubset->pentities, cur->name,
3824
0
                           NULL);
3825
0
      }
3826
0
      if (doc->extSubset != NULL) {
3827
0
          if (xmlHashLookup(doc->extSubset->entities, cur->name) == cur)
3828
0
        xmlHashRemoveEntry(doc->extSubset->entities, cur->name,
3829
0
                           NULL);
3830
0
          if (xmlHashLookup(doc->extSubset->pentities, cur->name) == cur)
3831
0
        xmlHashRemoveEntry(doc->extSubset->pentities, cur->name,
3832
0
                           NULL);
3833
0
      }
3834
0
  }
3835
0
    }
3836
58.5k
    if (cur->parent != NULL) {
3837
24.2k
  xmlNodePtr parent;
3838
24.2k
  parent = cur->parent;
3839
24.2k
  if (cur->type == XML_ATTRIBUTE_NODE) {
3840
0
      if (parent->properties == (xmlAttrPtr) cur)
3841
0
    parent->properties = ((xmlAttrPtr) cur)->next;
3842
24.2k
  } else {
3843
24.2k
      if (parent->children == cur)
3844
11.3k
    parent->children = cur->next;
3845
24.2k
      if (parent->last == cur)
3846
8.41k
    parent->last = cur->prev;
3847
24.2k
  }
3848
24.2k
  cur->parent = NULL;
3849
24.2k
    }
3850
58.5k
    if (cur->next != NULL)
3851
15.8k
        cur->next->prev = cur->prev;
3852
58.5k
    if (cur->prev != NULL)
3853
12.9k
        cur->prev->next = cur->next;
3854
58.5k
    cur->next = cur->prev = NULL;
3855
58.5k
}
3856
3857
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
3858
/**
3859
 * xmlReplaceNode:
3860
 * @old:  the old node
3861
 * @cur:  the node
3862
 *
3863
 * Unlink the old node from its current context, prune the new one
3864
 * at the same place. If @cur was already inserted in a document it is
3865
 * first unlinked from its existing context.
3866
 *
3867
 * See the note regarding namespaces in xmlAddChild.
3868
 *
3869
 * Returns the @old node
3870
 */
3871
xmlNodePtr
3872
0
xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
3873
0
    if (old == cur) return(NULL);
3874
0
    if ((old == NULL) || (old->type == XML_NAMESPACE_DECL) ||
3875
0
        (old->parent == NULL)) {
3876
0
  return(NULL);
3877
0
    }
3878
0
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3879
0
  xmlUnlinkNode(old);
3880
0
  return(old);
3881
0
    }
3882
0
    if (cur == old) {
3883
0
  return(old);
3884
0
    }
3885
0
    if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) {
3886
0
  return(old);
3887
0
    }
3888
0
    if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) {
3889
0
  return(old);
3890
0
    }
3891
0
    xmlUnlinkNode(cur);
3892
0
    xmlSetTreeDoc(cur, old->doc);
3893
0
    cur->parent = old->parent;
3894
0
    cur->next = old->next;
3895
0
    if (cur->next != NULL)
3896
0
  cur->next->prev = cur;
3897
0
    cur->prev = old->prev;
3898
0
    if (cur->prev != NULL)
3899
0
  cur->prev->next = cur;
3900
0
    if (cur->parent != NULL) {
3901
0
  if (cur->type == XML_ATTRIBUTE_NODE) {
3902
0
      if (cur->parent->properties == (xmlAttrPtr)old)
3903
0
    cur->parent->properties = ((xmlAttrPtr) cur);
3904
0
  } else {
3905
0
      if (cur->parent->children == old)
3906
0
    cur->parent->children = cur;
3907
0
      if (cur->parent->last == old)
3908
0
    cur->parent->last = cur;
3909
0
  }
3910
0
    }
3911
0
    old->next = old->prev = NULL;
3912
0
    old->parent = NULL;
3913
0
    return(old);
3914
0
}
3915
#endif /* LIBXML_TREE_ENABLED */
3916
3917
/************************************************************************
3918
 *                  *
3919
 *    Copy operations           *
3920
 *                  *
3921
 ************************************************************************/
3922
3923
/**
3924
 * xmlCopyNamespace:
3925
 * @cur:  the namespace
3926
 *
3927
 * Do a copy of the namespace.
3928
 *
3929
 * Returns: a new #xmlNsPtr, or NULL in case of error.
3930
 */
3931
xmlNsPtr
3932
0
xmlCopyNamespace(xmlNsPtr cur) {
3933
0
    xmlNsPtr ret;
3934
3935
0
    if (cur == NULL) return(NULL);
3936
0
    switch (cur->type) {
3937
0
  case XML_LOCAL_NAMESPACE:
3938
0
      ret = xmlNewNs(NULL, cur->href, cur->prefix);
3939
0
      break;
3940
0
  default:
3941
0
      return(NULL);
3942
0
    }
3943
0
    return(ret);
3944
0
}
3945
3946
/**
3947
 * xmlCopyNamespaceList:
3948
 * @cur:  the first namespace
3949
 *
3950
 * Do a copy of an namespace list.
3951
 *
3952
 * Returns: a new #xmlNsPtr, or NULL in case of error.
3953
 */
3954
xmlNsPtr
3955
0
xmlCopyNamespaceList(xmlNsPtr cur) {
3956
0
    xmlNsPtr ret = NULL;
3957
0
    xmlNsPtr p = NULL,q;
3958
3959
0
    while (cur != NULL) {
3960
0
        q = xmlCopyNamespace(cur);
3961
0
        if (q == NULL) {
3962
0
            xmlFreeNsList(ret);
3963
0
            return(NULL);
3964
0
        }
3965
0
  if (p == NULL) {
3966
0
      ret = p = q;
3967
0
  } else {
3968
0
      p->next = q;
3969
0
      p = q;
3970
0
  }
3971
0
  cur = cur->next;
3972
0
    }
3973
0
    return(ret);
3974
0
}
3975
3976
static xmlAttrPtr
3977
0
xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
3978
0
    xmlAttrPtr ret = NULL;
3979
3980
0
    if (cur == NULL) return(NULL);
3981
0
    if ((target != NULL) && (target->type != XML_ELEMENT_NODE))
3982
0
        return(NULL);
3983
0
    if (target != NULL)
3984
0
  ret = xmlNewDocProp(target->doc, cur->name, NULL);
3985
0
    else if (doc != NULL)
3986
0
  ret = xmlNewDocProp(doc, cur->name, NULL);
3987
0
    else if (cur->parent != NULL)
3988
0
  ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL);
3989
0
    else if (cur->children != NULL)
3990
0
  ret = xmlNewDocProp(cur->children->doc, cur->name, NULL);
3991
0
    else
3992
0
  ret = xmlNewDocProp(NULL, cur->name, NULL);
3993
0
    if (ret == NULL) return(NULL);
3994
0
    ret->parent = target;
3995
3996
0
    if ((cur->ns != NULL) && (target != NULL)) {
3997
0
      xmlNsPtr ns;
3998
3999
0
      ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
4000
0
      if (ns == NULL) {
4001
        /*
4002
         * Humm, we are copying an element whose namespace is defined
4003
         * out of the new tree scope. Search it in the original tree
4004
         * and add it at the top of the new tree
4005
         */
4006
0
        ns = xmlSearchNs(cur->doc, cur->parent, cur->ns->prefix);
4007
0
        if (ns != NULL) {
4008
0
          xmlNodePtr root = target;
4009
0
          xmlNodePtr pred = NULL;
4010
4011
0
          while (root->parent != NULL) {
4012
0
            pred = root;
4013
0
            root = root->parent;
4014
0
          }
4015
0
          if (root == (xmlNodePtr) target->doc) {
4016
            /* correct possibly cycling above the document elt */
4017
0
            root = pred;
4018
0
          }
4019
0
          ret->ns = xmlNewNs(root, ns->href, ns->prefix);
4020
0
          if (ret->ns == NULL)
4021
0
              goto error;
4022
0
        }
4023
0
      } else {
4024
        /*
4025
         * we have to find something appropriate here since
4026
         * we can't be sure, that the namespace we found is identified
4027
         * by the prefix
4028
         */
4029
0
        if (xmlStrEqual(ns->href, cur->ns->href)) {
4030
          /* this is the nice case */
4031
0
          ret->ns = ns;
4032
0
        } else {
4033
          /*
4034
           * we are in trouble: we need a new reconciled namespace.
4035
           * This is expensive
4036
           */
4037
0
          ret->ns = xmlNewReconciledNs(target->doc, target, cur->ns);
4038
0
          if (ret->ns == NULL)
4039
0
              goto error;
4040
0
        }
4041
0
      }
4042
4043
0
    } else
4044
0
        ret->ns = NULL;
4045
4046
0
    if (cur->children != NULL) {
4047
0
  xmlNodePtr tmp;
4048
4049
0
  ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret);
4050
0
        if (ret->children == NULL)
4051
0
            goto error;
4052
0
  ret->last = NULL;
4053
0
  tmp = ret->children;
4054
0
  while (tmp != NULL) {
4055
      /* tmp->parent = (xmlNodePtr)ret; */
4056
0
      if (tmp->next == NULL)
4057
0
          ret->last = tmp;
4058
0
      tmp = tmp->next;
4059
0
  }
4060
0
    }
4061
    /*
4062
     * Try to handle IDs
4063
     */
4064
0
    if ((target != NULL) && (cur != NULL) &&
4065
0
  (target->doc != NULL) && (cur->doc != NULL) &&
4066
0
  (cur->doc->ids != NULL) &&
4067
0
        (cur->parent != NULL) &&
4068
0
        (cur->children != NULL)) {
4069
0
        int res = xmlIsID(cur->doc, cur->parent, cur);
4070
4071
0
        if (res < 0)
4072
0
            goto error;
4073
0
  if (res != 0) {
4074
0
      xmlChar *id;
4075
4076
0
      id = xmlNodeListGetString(cur->doc, cur->children, 1);
4077
0
      if (id == NULL)
4078
0
                goto error;
4079
0
            res = xmlAddIDSafe(target->doc, id, ret, 0, NULL);
4080
0
      xmlFree(id);
4081
0
            if (res < 0)
4082
0
                goto error;
4083
0
  }
4084
0
    }
4085
0
    return(ret);
4086
4087
0
error:
4088
0
    xmlFreeProp(ret);
4089
0
    return(NULL);
4090
0
}
4091
4092
/**
4093
 * xmlCopyProp:
4094
 * @target:  the element where the attribute will be grafted
4095
 * @cur:  the attribute
4096
 *
4097
 * Do a copy of the attribute.
4098
 *
4099
 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4100
 */
4101
xmlAttrPtr
4102
0
xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
4103
0
  return xmlCopyPropInternal(NULL, target, cur);
4104
0
}
4105
4106
/**
4107
 * xmlCopyPropList:
4108
 * @target:  the element where the attributes will be grafted
4109
 * @cur:  the first attribute
4110
 *
4111
 * Do a copy of an attribute list.
4112
 *
4113
 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4114
 */
4115
xmlAttrPtr
4116
0
xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
4117
0
    xmlAttrPtr ret = NULL;
4118
0
    xmlAttrPtr p = NULL,q;
4119
4120
0
    if ((target != NULL) && (target->type != XML_ELEMENT_NODE))
4121
0
        return(NULL);
4122
0
    while (cur != NULL) {
4123
0
        q = xmlCopyProp(target, cur);
4124
0
  if (q == NULL) {
4125
0
            xmlFreePropList(ret);
4126
0
      return(NULL);
4127
0
        }
4128
0
  if (p == NULL) {
4129
0
      ret = p = q;
4130
0
  } else {
4131
0
      p->next = q;
4132
0
      q->prev = p;
4133
0
      p = q;
4134
0
  }
4135
0
  cur = cur->next;
4136
0
    }
4137
0
    return(ret);
4138
0
}
4139
4140
/*
4141
 * NOTE about the CopyNode operations !
4142
 *
4143
 * They are split into external and internal parts for one
4144
 * tricky reason: namespaces. Doing a direct copy of a node
4145
 * say RPM:Copyright without changing the namespace pointer to
4146
 * something else can produce stale links. One way to do it is
4147
 * to keep a reference counter but this doesn't work as soon
4148
 * as one moves the element or the subtree out of the scope of
4149
 * the existing namespace. The actual solution seems to be to add
4150
 * a copy of the namespace at the top of the copied tree if
4151
 * not available in the subtree.
4152
 * Hence two functions, the public front-end call the inner ones
4153
 * The argument "recursive" normally indicates a recursive copy
4154
 * of the node with values 0 (no) and 1 (yes).  For XInclude,
4155
 * however, we allow a value of 2 to indicate copy properties and
4156
 * namespace info, but don't recurse on children.
4157
 */
4158
4159
xmlNodePtr
4160
xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
4161
0
                  int extended) {
4162
0
    xmlNodePtr ret;
4163
4164
0
    if (node == NULL) return(NULL);
4165
0
    switch (node->type) {
4166
0
        case XML_TEXT_NODE:
4167
0
        case XML_CDATA_SECTION_NODE:
4168
0
        case XML_ELEMENT_NODE:
4169
0
        case XML_DOCUMENT_FRAG_NODE:
4170
0
        case XML_ENTITY_REF_NODE:
4171
0
        case XML_ENTITY_NODE:
4172
0
        case XML_PI_NODE:
4173
0
        case XML_COMMENT_NODE:
4174
0
        case XML_XINCLUDE_START:
4175
0
        case XML_XINCLUDE_END:
4176
0
      break;
4177
0
        case XML_ATTRIBUTE_NODE:
4178
0
    return((xmlNodePtr) xmlCopyPropInternal(doc, parent, (xmlAttrPtr) node));
4179
0
        case XML_NAMESPACE_DECL:
4180
0
      return((xmlNodePtr) xmlCopyNamespaceList((xmlNsPtr) node));
4181
4182
0
        case XML_DOCUMENT_NODE:
4183
0
        case XML_HTML_DOCUMENT_NODE:
4184
0
#ifdef LIBXML_TREE_ENABLED
4185
0
      return((xmlNodePtr) xmlCopyDoc((xmlDocPtr) node, extended));
4186
0
#endif /* LIBXML_TREE_ENABLED */
4187
0
        case XML_DOCUMENT_TYPE_NODE:
4188
0
        case XML_NOTATION_NODE:
4189
0
        case XML_DTD_NODE:
4190
0
        case XML_ELEMENT_DECL:
4191
0
        case XML_ATTRIBUTE_DECL:
4192
0
        case XML_ENTITY_DECL:
4193
0
            return(NULL);
4194
0
    }
4195
4196
    /*
4197
     * Allocate a new node and fill the fields.
4198
     */
4199
0
    ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
4200
0
    if (ret == NULL)
4201
0
  return(NULL);
4202
0
    memset(ret, 0, sizeof(xmlNode));
4203
0
    ret->type = node->type;
4204
4205
0
    ret->doc = doc;
4206
0
    ret->parent = parent;
4207
0
    if (node->name == xmlStringText)
4208
0
  ret->name = xmlStringText;
4209
0
    else if (node->name == xmlStringTextNoenc)
4210
0
  ret->name = xmlStringTextNoenc;
4211
0
    else if (node->name == xmlStringComment)
4212
0
  ret->name = xmlStringComment;
4213
0
    else if (node->name != NULL) {
4214
0
        if ((doc != NULL) && (doc->dict != NULL))
4215
0
      ret->name = xmlDictLookup(doc->dict, node->name, -1);
4216
0
  else
4217
0
      ret->name = xmlStrdup(node->name);
4218
0
        if (ret->name == NULL)
4219
0
            goto error;
4220
0
    }
4221
0
    if ((node->type != XML_ELEMENT_NODE) &&
4222
0
  (node->content != NULL) &&
4223
0
  (node->type != XML_ENTITY_REF_NODE) &&
4224
0
  (node->type != XML_XINCLUDE_END) &&
4225
0
  (node->type != XML_XINCLUDE_START)) {
4226
0
  ret->content = xmlStrdup(node->content);
4227
0
        if (ret->content == NULL)
4228
0
            goto error;
4229
0
    }else{
4230
0
      if (node->type == XML_ELEMENT_NODE)
4231
0
        ret->line = node->line;
4232
0
    }
4233
0
    if (parent != NULL) {
4234
0
  xmlNodePtr tmp;
4235
4236
  /*
4237
   * this is a tricky part for the node register thing:
4238
   * in case ret does get coalesced in xmlAddChild
4239
   * the deregister-node callback is called; so we register ret now already
4240
   */
4241
0
  if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
4242
0
      xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
4243
4244
        /*
4245
         * Note that since ret->parent is already set, xmlAddChild will
4246
         * return early and not actually insert the node. It will only
4247
         * coalesce text nodes and unnecessarily call xmlSetTreeDoc.
4248
         * Assuming that the subtree to be copied always has its text
4249
         * nodes coalesced, the somewhat confusing call to xmlAddChild
4250
         * could be removed.
4251
         */
4252
0
        tmp = xmlAddChild(parent, ret);
4253
  /* node could have coalesced */
4254
0
  if (tmp != ret)
4255
0
      return(tmp);
4256
0
    }
4257
4258
0
    if (!extended)
4259
0
  goto out;
4260
0
    if (((node->type == XML_ELEMENT_NODE) ||
4261
0
         (node->type == XML_XINCLUDE_START)) && (node->nsDef != NULL)) {
4262
0
        ret->nsDef = xmlCopyNamespaceList(node->nsDef);
4263
0
        if (ret->nsDef == NULL)
4264
0
            goto error;
4265
0
    }
4266
4267
0
    if ((node->type == XML_ELEMENT_NODE) && (node->ns != NULL)) {
4268
0
        xmlNsPtr ns;
4269
4270
0
  ns = xmlSearchNs(doc, ret, node->ns->prefix);
4271
0
  if (ns == NULL) {
4272
      /*
4273
       * Humm, we are copying an element whose namespace is defined
4274
       * out of the new tree scope. Search it in the original tree
4275
       * and add it at the top of the new tree.
4276
             *
4277
             * TODO: Searching the original tree seems unnecessary. We
4278
             * already have a namespace URI.
4279
       */
4280
0
      ns = xmlSearchNs(node->doc, node, node->ns->prefix);
4281
0
      if (ns != NULL) {
4282
0
          xmlNodePtr root = ret;
4283
4284
0
    while (root->parent != NULL) root = root->parent;
4285
0
    ret->ns = xmlNewNs(root, ns->href, ns->prefix);
4286
0
            } else {
4287
0
                ret->ns = xmlNewReconciledNs(doc, ret, node->ns);
4288
0
      }
4289
0
            if (ret->ns == NULL)
4290
0
                goto error;
4291
0
  } else {
4292
      /*
4293
       * reference the existing namespace definition in our own tree.
4294
       */
4295
0
      ret->ns = ns;
4296
0
  }
4297
0
    }
4298
0
    if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL)) {
4299
0
        ret->properties = xmlCopyPropList(ret, node->properties);
4300
0
        if (ret->properties == NULL)
4301
0
            goto error;
4302
0
    }
4303
0
    if (node->type == XML_ENTITY_REF_NODE) {
4304
0
  if ((doc == NULL) || (node->doc != doc)) {
4305
      /*
4306
       * The copied node will go into a separate document, so
4307
       * to avoid dangling references to the ENTITY_DECL node
4308
       * we cannot keep the reference. Try to find it in the
4309
       * target document.
4310
       */
4311
0
      ret->children = (xmlNodePtr) xmlGetDocEntity(doc, ret->name);
4312
0
  } else {
4313
0
            ret->children = node->children;
4314
0
  }
4315
0
  ret->last = ret->children;
4316
0
    } else if ((node->children != NULL) && (extended != 2)) {
4317
0
        xmlNodePtr cur, insert;
4318
4319
0
        cur = node->children;
4320
0
        insert = ret;
4321
0
        while (cur != NULL) {
4322
0
            xmlNodePtr copy = xmlStaticCopyNode(cur, doc, insert, 2);
4323
0
            if (copy == NULL)
4324
0
                goto error;
4325
4326
            /* Check for coalesced text nodes */
4327
0
            if (insert->last != copy) {
4328
0
                if (insert->last == NULL) {
4329
0
                    insert->children = copy;
4330
0
                } else {
4331
0
                    copy->prev = insert->last;
4332
0
                    insert->last->next = copy;
4333
0
                }
4334
0
                insert->last = copy;
4335
0
            }
4336
4337
0
            if ((cur->type != XML_ENTITY_REF_NODE) &&
4338
0
                (cur->children != NULL)) {
4339
0
                cur = cur->children;
4340
0
                insert = copy;
4341
0
                continue;
4342
0
            }
4343
4344
0
            while (1) {
4345
0
                if (cur->next != NULL) {
4346
0
                    cur = cur->next;
4347
0
                    break;
4348
0
                }
4349
4350
0
                cur = cur->parent;
4351
0
                insert = insert->parent;
4352
0
                if (cur == node) {
4353
0
                    cur = NULL;
4354
0
                    break;
4355
0
                }
4356
0
            }
4357
0
        }
4358
0
    }
4359
4360
0
out:
4361
    /* if parent != NULL we already registered the node above */
4362
0
    if ((parent == NULL) &&
4363
0
        ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)))
4364
0
  xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
4365
0
    return(ret);
4366
4367
0
error:
4368
0
    xmlFreeNode(ret);
4369
0
    return(NULL);
4370
0
}
4371
4372
xmlNodePtr
4373
0
xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
4374
0
    xmlNodePtr ret = NULL;
4375
0
    xmlNodePtr p = NULL,q;
4376
0
    xmlDtdPtr newSubset = NULL;
4377
0
    int linkedSubset = 0;
4378
4379
0
    while (node != NULL) {
4380
0
#ifdef LIBXML_TREE_ENABLED
4381
0
  if (node->type == XML_DTD_NODE ) {
4382
0
      if (doc == NULL) {
4383
0
    node = node->next;
4384
0
    continue;
4385
0
      }
4386
0
      if ((doc->intSubset == NULL) && (newSubset == NULL)) {
4387
0
    q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node );
4388
0
    if (q == NULL) goto error;
4389
0
    q->doc = doc;
4390
0
    q->parent = parent;
4391
0
    newSubset = (xmlDtdPtr) q;
4392
0
    xmlAddChild(parent, q);
4393
0
      } else {
4394
0
                linkedSubset = 1;
4395
0
    q = (xmlNodePtr) doc->intSubset;
4396
0
    xmlAddChild(parent, q);
4397
0
      }
4398
0
  } else
4399
0
#endif /* LIBXML_TREE_ENABLED */
4400
0
      q = xmlStaticCopyNode(node, doc, parent, 1);
4401
0
  if (q == NULL) goto error;
4402
0
  if (ret == NULL) {
4403
0
      q->prev = NULL;
4404
0
      ret = p = q;
4405
0
  } else if (p != q) {
4406
  /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */
4407
0
      p->next = q;
4408
0
      q->prev = p;
4409
0
      p = q;
4410
0
  }
4411
0
  node = node->next;
4412
0
    }
4413
0
    if ((doc != NULL) && (newSubset != NULL))
4414
0
        doc->intSubset = newSubset;
4415
0
    return(ret);
4416
0
error:
4417
0
    xmlFreeNodeList(ret);
4418
0
    if (linkedSubset != 0) {
4419
0
        doc->intSubset->next = NULL;
4420
0
        doc->intSubset->prev = NULL;
4421
0
    }
4422
0
    return(NULL);
4423
0
}
4424
4425
/**
4426
 * xmlCopyNode:
4427
 * @node:  the node
4428
 * @extended:   if 1 do a recursive copy (properties, namespaces and children
4429
 *      when applicable)
4430
 *    if 2 copy properties and namespaces (when applicable)
4431
 *
4432
 * Do a copy of the node.
4433
 *
4434
 * Returns: a new #xmlNodePtr, or NULL in case of error.
4435
 */
4436
xmlNodePtr
4437
0
xmlCopyNode(xmlNodePtr node, int extended) {
4438
0
    xmlNodePtr ret;
4439
4440
0
    ret = xmlStaticCopyNode(node, NULL, NULL, extended);
4441
0
    return(ret);
4442
0
}
4443
4444
/**
4445
 * xmlDocCopyNode:
4446
 * @node:  the node
4447
 * @doc:  the document
4448
 * @extended:   if 1 do a recursive copy (properties, namespaces and children
4449
 *      when applicable)
4450
 *    if 2 copy properties and namespaces (when applicable)
4451
 *
4452
 * Do a copy of the node to a given document.
4453
 *
4454
 * Returns: a new #xmlNodePtr, or NULL in case of error.
4455
 */
4456
xmlNodePtr
4457
0
xmlDocCopyNode(xmlNodePtr node, xmlDocPtr doc, int extended) {
4458
0
    xmlNodePtr ret;
4459
4460
0
    ret = xmlStaticCopyNode(node, doc, NULL, extended);
4461
0
    return(ret);
4462
0
}
4463
4464
/**
4465
 * xmlDocCopyNodeList:
4466
 * @doc: the target document
4467
 * @node:  the first node in the list.
4468
 *
4469
 * Do a recursive copy of the node list.
4470
 *
4471
 * Returns: a new #xmlNodePtr, or NULL in case of error.
4472
 */
4473
0
xmlNodePtr xmlDocCopyNodeList(xmlDocPtr doc, xmlNodePtr node) {
4474
0
    xmlNodePtr ret = xmlStaticCopyNodeList(node, doc, NULL);
4475
0
    return(ret);
4476
0
}
4477
4478
/**
4479
 * xmlCopyNodeList:
4480
 * @node:  the first node in the list.
4481
 *
4482
 * Do a recursive copy of the node list.
4483
 * Use xmlDocCopyNodeList() if possible to ensure string interning.
4484
 *
4485
 * Returns: a new #xmlNodePtr, or NULL in case of error.
4486
 */
4487
0
xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
4488
0
    xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
4489
0
    return(ret);
4490
0
}
4491
4492
#if defined(LIBXML_TREE_ENABLED)
4493
/**
4494
 * xmlCopyDtd:
4495
 * @dtd:  the dtd
4496
 *
4497
 * Do a copy of the dtd.
4498
 *
4499
 * Returns: a new #xmlDtdPtr, or NULL in case of error.
4500
 */
4501
xmlDtdPtr
4502
0
xmlCopyDtd(xmlDtdPtr dtd) {
4503
0
    xmlDtdPtr ret;
4504
0
    xmlNodePtr cur, p = NULL, q;
4505
4506
0
    if (dtd == NULL) return(NULL);
4507
0
    ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
4508
0
    if (ret == NULL) return(NULL);
4509
0
    if (dtd->entities != NULL) {
4510
0
        ret->entities = (void *) xmlCopyEntitiesTable(
4511
0
                      (xmlEntitiesTablePtr) dtd->entities);
4512
0
        if (ret->entities == NULL)
4513
0
            goto error;
4514
0
    }
4515
0
    if (dtd->notations != NULL) {
4516
0
        ret->notations = (void *) xmlCopyNotationTable(
4517
0
                      (xmlNotationTablePtr) dtd->notations);
4518
0
        if (ret->notations == NULL)
4519
0
            goto error;
4520
0
    }
4521
0
    if (dtd->elements != NULL) {
4522
0
        ret->elements = (void *) xmlCopyElementTable(
4523
0
                      (xmlElementTablePtr) dtd->elements);
4524
0
        if (ret->elements == NULL)
4525
0
            goto error;
4526
0
    }
4527
0
    if (dtd->attributes != NULL) {
4528
0
        ret->attributes = (void *) xmlCopyAttributeTable(
4529
0
                      (xmlAttributeTablePtr) dtd->attributes);
4530
0
        if (ret->attributes == NULL)
4531
0
            goto error;
4532
0
    }
4533
0
    if (dtd->pentities != NULL) {
4534
0
  ret->pentities = (void *) xmlCopyEntitiesTable(
4535
0
          (xmlEntitiesTablePtr) dtd->pentities);
4536
0
        if (ret->pentities == NULL)
4537
0
            goto error;
4538
0
    }
4539
4540
0
    cur = dtd->children;
4541
0
    while (cur != NULL) {
4542
0
  q = NULL;
4543
4544
0
  if (cur->type == XML_ENTITY_DECL) {
4545
0
      xmlEntityPtr tmp = (xmlEntityPtr) cur;
4546
0
      switch (tmp->etype) {
4547
0
    case XML_INTERNAL_GENERAL_ENTITY:
4548
0
    case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
4549
0
    case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
4550
0
        q = (xmlNodePtr) xmlGetEntityFromDtd(ret, tmp->name);
4551
0
        break;
4552
0
    case XML_INTERNAL_PARAMETER_ENTITY:
4553
0
    case XML_EXTERNAL_PARAMETER_ENTITY:
4554
0
        q = (xmlNodePtr)
4555
0
      xmlGetParameterEntityFromDtd(ret, tmp->name);
4556
0
        break;
4557
0
    case XML_INTERNAL_PREDEFINED_ENTITY:
4558
0
        break;
4559
0
      }
4560
0
  } else if (cur->type == XML_ELEMENT_DECL) {
4561
0
      xmlElementPtr tmp = (xmlElementPtr) cur;
4562
0
      q = (xmlNodePtr)
4563
0
    xmlGetDtdQElementDesc(ret, tmp->name, tmp->prefix);
4564
0
  } else if (cur->type == XML_ATTRIBUTE_DECL) {
4565
0
      xmlAttributePtr tmp = (xmlAttributePtr) cur;
4566
0
      q = (xmlNodePtr)
4567
0
    xmlGetDtdQAttrDesc(ret, tmp->elem, tmp->name, tmp->prefix);
4568
0
  } else if (cur->type == XML_COMMENT_NODE) {
4569
0
      q = xmlCopyNode(cur, 0);
4570
0
            if (q == NULL)
4571
0
                goto error;
4572
0
  }
4573
4574
0
  if (q == NULL) {
4575
0
      cur = cur->next;
4576
0
      continue;
4577
0
  }
4578
4579
0
  if (p == NULL)
4580
0
      ret->children = q;
4581
0
  else
4582
0
      p->next = q;
4583
4584
0
  q->prev = p;
4585
0
  q->parent = (xmlNodePtr) ret;
4586
0
  q->next = NULL;
4587
0
  ret->last = q;
4588
0
  p = q;
4589
0
  cur = cur->next;
4590
0
    }
4591
4592
0
    return(ret);
4593
4594
0
error:
4595
0
    xmlFreeDtd(ret);
4596
0
    return(NULL);
4597
0
}
4598
#endif
4599
4600
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
4601
/**
4602
 * xmlCopyDoc:
4603
 * @doc:  the document
4604
 * @recursive:  if not zero do a recursive copy.
4605
 *
4606
 * Do a copy of the document info. If recursive, the content tree will
4607
 * be copied too as well as DTD, namespaces and entities.
4608
 *
4609
 * Returns: a new #xmlDocPtr, or NULL in case of error.
4610
 */
4611
xmlDocPtr
4612
0
xmlCopyDoc(xmlDocPtr doc, int recursive) {
4613
0
    xmlDocPtr ret;
4614
4615
0
    if (doc == NULL) return(NULL);
4616
0
    ret = xmlNewDoc(doc->version);
4617
0
    if (ret == NULL) return(NULL);
4618
0
    ret->type = doc->type;
4619
0
    if (doc->name != NULL) {
4620
0
        ret->name = xmlMemStrdup(doc->name);
4621
0
        if (ret->name == NULL)
4622
0
            goto error;
4623
0
    }
4624
0
    if (doc->encoding != NULL) {
4625
0
        ret->encoding = xmlStrdup(doc->encoding);
4626
0
        if (ret->encoding == NULL)
4627
0
            goto error;
4628
0
    }
4629
0
    if (doc->URL != NULL) {
4630
0
        ret->URL = xmlStrdup(doc->URL);
4631
0
        if (ret->URL == NULL)
4632
0
            goto error;
4633
0
    }
4634
0
    ret->charset = doc->charset;
4635
0
    ret->compression = doc->compression;
4636
0
    ret->standalone = doc->standalone;
4637
0
    if (!recursive) return(ret);
4638
4639
0
    ret->last = NULL;
4640
0
    ret->children = NULL;
4641
0
#ifdef LIBXML_TREE_ENABLED
4642
0
    if (doc->intSubset != NULL) {
4643
0
        ret->intSubset = xmlCopyDtd(doc->intSubset);
4644
0
  if (ret->intSubset == NULL)
4645
0
            goto error;
4646
0
  xmlSetTreeDoc((xmlNodePtr)ret->intSubset, ret);
4647
0
  ret->intSubset->parent = ret;
4648
0
    }
4649
0
#endif
4650
0
    if (doc->oldNs != NULL) {
4651
0
        ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
4652
0
        if (ret->oldNs == NULL)
4653
0
            goto error;
4654
0
    }
4655
0
    if (doc->children != NULL) {
4656
0
  xmlNodePtr tmp;
4657
4658
0
  ret->children = xmlStaticCopyNodeList(doc->children, ret,
4659
0
                                   (xmlNodePtr)ret);
4660
0
        if (ret->children == NULL)
4661
0
            goto error;
4662
0
  ret->last = NULL;
4663
0
  tmp = ret->children;
4664
0
  while (tmp != NULL) {
4665
0
      if (tmp->next == NULL)
4666
0
          ret->last = tmp;
4667
0
      tmp = tmp->next;
4668
0
  }
4669
0
    }
4670
0
    return(ret);
4671
4672
0
error:
4673
0
    xmlFreeDoc(ret);
4674
0
    return(NULL);
4675
0
}
4676
#endif /* LIBXML_TREE_ENABLED */
4677
4678
/************************************************************************
4679
 *                  *
4680
 *    Content access functions        *
4681
 *                  *
4682
 ************************************************************************/
4683
4684
/**
4685
 * xmlGetLineNoInternal:
4686
 * @node: valid node
4687
 * @depth: used to limit any risk of recursion
4688
 *
4689
 * Get line number of @node.
4690
 * Try to override the limitation of lines being store in 16 bits ints
4691
 *
4692
 * Returns the line number if successful, -1 otherwise
4693
 */
4694
static long
4695
xmlGetLineNoInternal(const xmlNode *node, int depth)
4696
1.46k
{
4697
1.46k
    long result = -1;
4698
4699
1.46k
    if (depth >= 5)
4700
0
        return(-1);
4701
4702
1.46k
    if (!node)
4703
0
        return result;
4704
1.46k
    if ((node->type == XML_ELEMENT_NODE) ||
4705
1.46k
        (node->type == XML_TEXT_NODE) ||
4706
1.46k
  (node->type == XML_COMMENT_NODE) ||
4707
1.46k
  (node->type == XML_PI_NODE)) {
4708
1.46k
  if (node->line == 65535) {
4709
0
      if ((node->type == XML_TEXT_NODE) && (node->psvi != NULL))
4710
0
          result = (long) (ptrdiff_t) node->psvi;
4711
0
      else if ((node->type == XML_ELEMENT_NODE) &&
4712
0
               (node->children != NULL))
4713
0
          result = xmlGetLineNoInternal(node->children, depth + 1);
4714
0
      else if (node->next != NULL)
4715
0
          result = xmlGetLineNoInternal(node->next, depth + 1);
4716
0
      else if (node->prev != NULL)
4717
0
          result = xmlGetLineNoInternal(node->prev, depth + 1);
4718
0
  }
4719
1.46k
  if ((result == -1) || (result == 65535))
4720
1.46k
      result = (long) node->line;
4721
1.46k
    } else if ((node->prev != NULL) &&
4722
0
             ((node->prev->type == XML_ELEMENT_NODE) ||
4723
0
        (node->prev->type == XML_TEXT_NODE) ||
4724
0
        (node->prev->type == XML_COMMENT_NODE) ||
4725
0
        (node->prev->type == XML_PI_NODE)))
4726
0
        result = xmlGetLineNoInternal(node->prev, depth + 1);
4727
0
    else if ((node->parent != NULL) &&
4728
0
             (node->parent->type == XML_ELEMENT_NODE))
4729
0
        result = xmlGetLineNoInternal(node->parent, depth + 1);
4730
4731
1.46k
    return result;
4732
1.46k
}
4733
4734
/**
4735
 * xmlGetLineNo:
4736
 * @node: valid node
4737
 *
4738
 * Get line number of @node.
4739
 * Try to override the limitation of lines being store in 16 bits ints
4740
 * if XML_PARSE_BIG_LINES parser option was used
4741
 *
4742
 * Returns the line number if successful, -1 otherwise
4743
 */
4744
long
4745
xmlGetLineNo(const xmlNode *node)
4746
1.46k
{
4747
1.46k
    return(xmlGetLineNoInternal(node, 0));
4748
1.46k
}
4749
4750
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
4751
/**
4752
 * xmlGetNodePath:
4753
 * @node: a node
4754
 *
4755
 * Build a structure based Path for the given node
4756
 *
4757
 * Returns the new path or NULL in case of error. The caller must free
4758
 *     the returned string
4759
 */
4760
xmlChar *
4761
xmlGetNodePath(const xmlNode *node)
4762
0
{
4763
0
    const xmlNode *cur, *tmp, *next;
4764
0
    xmlChar *buffer = NULL, *temp;
4765
0
    size_t buf_len;
4766
0
    xmlChar *buf;
4767
0
    const char *sep;
4768
0
    const char *name;
4769
0
    char nametemp[100];
4770
0
    int occur = 0, generic;
4771
4772
0
    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
4773
0
        return (NULL);
4774
4775
0
    buf_len = 500;
4776
0
    buffer = (xmlChar *) xmlMallocAtomic(buf_len);
4777
0
    if (buffer == NULL)
4778
0
        return (NULL);
4779
0
    buf = (xmlChar *) xmlMallocAtomic(buf_len);
4780
0
    if (buf == NULL) {
4781
0
        xmlFree(buffer);
4782
0
        return (NULL);
4783
0
    }
4784
4785
0
    buffer[0] = 0;
4786
0
    cur = node;
4787
0
    do {
4788
0
        name = "";
4789
0
        sep = "?";
4790
0
        occur = 0;
4791
0
        if ((cur->type == XML_DOCUMENT_NODE) ||
4792
0
            (cur->type == XML_HTML_DOCUMENT_NODE)) {
4793
0
            if (buffer[0] == '/')
4794
0
                break;
4795
0
            sep = "/";
4796
0
            next = NULL;
4797
0
        } else if (cur->type == XML_ELEMENT_NODE) {
4798
0
      generic = 0;
4799
0
            sep = "/";
4800
0
            name = (const char *) cur->name;
4801
0
            if (cur->ns) {
4802
0
    if (cur->ns->prefix != NULL) {
4803
0
                    snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",
4804
0
      (char *)cur->ns->prefix, (char *)cur->name);
4805
0
        nametemp[sizeof(nametemp) - 1] = 0;
4806
0
        name = nametemp;
4807
0
    } else {
4808
        /*
4809
        * We cannot express named elements in the default
4810
        * namespace, so use "*".
4811
        */
4812
0
        generic = 1;
4813
0
        name = "*";
4814
0
    }
4815
0
            }
4816
0
            next = cur->parent;
4817
4818
            /*
4819
             * Thumbler index computation
4820
       * TODO: the occurrence test seems bogus for namespaced names
4821
             */
4822
0
            tmp = cur->prev;
4823
0
            while (tmp != NULL) {
4824
0
                if ((tmp->type == XML_ELEMENT_NODE) &&
4825
0
        (generic ||
4826
0
         (xmlStrEqual(cur->name, tmp->name) &&
4827
0
         ((tmp->ns == cur->ns) ||
4828
0
          ((tmp->ns != NULL) && (cur->ns != NULL) &&
4829
0
           (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))
4830
0
                    occur++;
4831
0
                tmp = tmp->prev;
4832
0
            }
4833
0
            if (occur == 0) {
4834
0
                tmp = cur->next;
4835
0
                while (tmp != NULL && occur == 0) {
4836
0
                    if ((tmp->type == XML_ELEMENT_NODE) &&
4837
0
      (generic ||
4838
0
       (xmlStrEqual(cur->name, tmp->name) &&
4839
0
       ((tmp->ns == cur->ns) ||
4840
0
        ((tmp->ns != NULL) && (cur->ns != NULL) &&
4841
0
         (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))
4842
0
                        occur++;
4843
0
                    tmp = tmp->next;
4844
0
                }
4845
0
                if (occur != 0)
4846
0
                    occur = 1;
4847
0
            } else
4848
0
                occur++;
4849
0
        } else if (cur->type == XML_COMMENT_NODE) {
4850
0
            sep = "/";
4851
0
      name = "comment()";
4852
0
            next = cur->parent;
4853
4854
            /*
4855
             * Thumbler index computation
4856
             */
4857
0
            tmp = cur->prev;
4858
0
            while (tmp != NULL) {
4859
0
                if (tmp->type == XML_COMMENT_NODE)
4860
0
        occur++;
4861
0
                tmp = tmp->prev;
4862
0
            }
4863
0
            if (occur == 0) {
4864
0
                tmp = cur->next;
4865
0
                while (tmp != NULL && occur == 0) {
4866
0
        if (tmp->type == XML_COMMENT_NODE)
4867
0
            occur++;
4868
0
                    tmp = tmp->next;
4869
0
                }
4870
0
                if (occur != 0)
4871
0
                    occur = 1;
4872
0
            } else
4873
0
                occur++;
4874
0
        } else if ((cur->type == XML_TEXT_NODE) ||
4875
0
                   (cur->type == XML_CDATA_SECTION_NODE)) {
4876
0
            sep = "/";
4877
0
      name = "text()";
4878
0
            next = cur->parent;
4879
4880
            /*
4881
             * Thumbler index computation
4882
             */
4883
0
            tmp = cur->prev;
4884
0
            while (tmp != NULL) {
4885
0
                if ((tmp->type == XML_TEXT_NODE) ||
4886
0
        (tmp->type == XML_CDATA_SECTION_NODE))
4887
0
        occur++;
4888
0
                tmp = tmp->prev;
4889
0
            }
4890
      /*
4891
      * Evaluate if this is the only text- or CDATA-section-node;
4892
      * if yes, then we'll get "text()", otherwise "text()[1]".
4893
      */
4894
0
            if (occur == 0) {
4895
0
                tmp = cur->next;
4896
0
                while (tmp != NULL) {
4897
0
        if ((tmp->type == XML_TEXT_NODE) ||
4898
0
      (tmp->type == XML_CDATA_SECTION_NODE))
4899
0
        {
4900
0
      occur = 1;
4901
0
      break;
4902
0
        }
4903
0
        tmp = tmp->next;
4904
0
    }
4905
0
            } else
4906
0
                occur++;
4907
0
        } else if (cur->type == XML_PI_NODE) {
4908
0
            sep = "/";
4909
0
      snprintf(nametemp, sizeof(nametemp) - 1,
4910
0
         "processing-instruction('%s')", (char *)cur->name);
4911
0
            nametemp[sizeof(nametemp) - 1] = 0;
4912
0
            name = nametemp;
4913
4914
0
      next = cur->parent;
4915
4916
            /*
4917
             * Thumbler index computation
4918
             */
4919
0
            tmp = cur->prev;
4920
0
            while (tmp != NULL) {
4921
0
                if ((tmp->type == XML_PI_NODE) &&
4922
0
        (xmlStrEqual(cur->name, tmp->name)))
4923
0
                    occur++;
4924
0
                tmp = tmp->prev;
4925
0
            }
4926
0
            if (occur == 0) {
4927
0
                tmp = cur->next;
4928
0
                while (tmp != NULL && occur == 0) {
4929
0
                    if ((tmp->type == XML_PI_NODE) &&
4930
0
      (xmlStrEqual(cur->name, tmp->name)))
4931
0
                        occur++;
4932
0
                    tmp = tmp->next;
4933
0
                }
4934
0
                if (occur != 0)
4935
0
                    occur = 1;
4936
0
            } else
4937
0
                occur++;
4938
4939
0
        } else if (cur->type == XML_ATTRIBUTE_NODE) {
4940
0
            sep = "/@";
4941
0
            name = (const char *) (((xmlAttrPtr) cur)->name);
4942
0
            if (cur->ns) {
4943
0
          if (cur->ns->prefix != NULL)
4944
0
                    snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",
4945
0
      (char *)cur->ns->prefix, (char *)cur->name);
4946
0
    else
4947
0
        snprintf(nametemp, sizeof(nametemp) - 1, "%s",
4948
0
      (char *)cur->name);
4949
0
                nametemp[sizeof(nametemp) - 1] = 0;
4950
0
                name = nametemp;
4951
0
            }
4952
0
            next = ((xmlAttrPtr) cur)->parent;
4953
0
        } else {
4954
0
            xmlFree(buf);
4955
0
            xmlFree(buffer);
4956
0
            return (NULL);
4957
0
        }
4958
4959
        /*
4960
         * Make sure there is enough room
4961
         */
4962
0
        if (xmlStrlen(buffer) + sizeof(nametemp) + 20 > buf_len) {
4963
0
            buf_len =
4964
0
                2 * buf_len + xmlStrlen(buffer) + sizeof(nametemp) + 20;
4965
0
            temp = (xmlChar *) xmlRealloc(buffer, buf_len);
4966
0
            if (temp == NULL) {
4967
0
                xmlFree(buf);
4968
0
                xmlFree(buffer);
4969
0
                return (NULL);
4970
0
            }
4971
0
            buffer = temp;
4972
0
            temp = (xmlChar *) xmlRealloc(buf, buf_len);
4973
0
            if (temp == NULL) {
4974
0
                xmlFree(buf);
4975
0
                xmlFree(buffer);
4976
0
                return (NULL);
4977
0
            }