Coverage Report

Created: 2024-02-28 06:07

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