~ubuntu-branches/ubuntu/wily/libxml2/wily-proposed

« back to all changes in this revision

Viewing changes to .pc/0021-Fix-a-couple-of-missing-NULL-checks.patch/tree.c

  • Committer: Package Import Robot
  • Author(s): Aron Xu
  • Date: 2014-10-26 07:04:50 UTC
  • mfrom: (43.2.7 sid)
  • Revision ID: package-import@ubuntu.com-20141026070450-rmcqvcqn8peeuebs
Tags: 2.9.2+dfsg1-1
* New upstream release (Closes: #765722, CVE-2014-3660)
* Remove no-longer-needed upstream patches
* Update distro patch
* Std-ver: 3.9.5 -> 3.9.6, no change.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * tree.c : implementation of access function for an XML tree.
3
 
 *
4
 
 * References:
5
 
 *   XHTML 1.0 W3C REC: http://www.w3.org/TR/2002/REC-xhtml1-20020801/
6
 
 *
7
 
 * See Copyright for the status of this software.
8
 
 *
9
 
 * daniel@veillard.com
10
 
 *
11
 
 */
12
 
 
13
 
#define IN_LIBXML
14
 
#include "libxml.h"
15
 
 
16
 
#include <string.h> /* for memset() only ! */
17
 
#include <limits.h>
18
 
#ifdef HAVE_CTYPE_H
19
 
#include <ctype.h>
20
 
#endif
21
 
#ifdef HAVE_STDLIB_H
22
 
#include <stdlib.h>
23
 
#endif
24
 
#ifdef HAVE_ZLIB_H
25
 
#include <zlib.h>
26
 
#endif
27
 
 
28
 
#include <libxml/xmlmemory.h>
29
 
#include <libxml/tree.h>
30
 
#include <libxml/parser.h>
31
 
#include <libxml/uri.h>
32
 
#include <libxml/entities.h>
33
 
#include <libxml/valid.h>
34
 
#include <libxml/xmlerror.h>
35
 
#include <libxml/parserInternals.h>
36
 
#include <libxml/globals.h>
37
 
#ifdef LIBXML_HTML_ENABLED
38
 
#include <libxml/HTMLtree.h>
39
 
#endif
40
 
#ifdef LIBXML_DEBUG_ENABLED
41
 
#include <libxml/debugXML.h>
42
 
#endif
43
 
 
44
 
#include "buf.h"
45
 
#include "save.h"
46
 
 
47
 
int __xmlRegisterCallbacks = 0;
48
 
 
49
 
/************************************************************************
50
 
 *                                                                      *
51
 
 *              Forward declarations                                    *
52
 
 *                                                                      *
53
 
 ************************************************************************/
54
 
 
55
 
static xmlNsPtr
56
 
xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns);
57
 
 
58
 
static xmlChar* xmlGetPropNodeValueInternal(xmlAttrPtr prop);
59
 
 
60
 
/************************************************************************
61
 
 *                                                                      *
62
 
 *              Tree memory error handler                               *
63
 
 *                                                                      *
64
 
 ************************************************************************/
65
 
/**
66
 
 * xmlTreeErrMemory:
67
 
 * @extra:  extra informations
68
 
 *
69
 
 * Handle an out of memory condition
70
 
 */
71
 
static void
72
 
xmlTreeErrMemory(const char *extra)
73
 
{
74
 
    __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra);
75
 
}
76
 
 
77
 
/**
78
 
 * xmlTreeErr:
79
 
 * @code:  the error number
80
 
 * @extra:  extra informations
81
 
 *
82
 
 * Handle an out of memory condition
83
 
 */
84
 
static void
85
 
xmlTreeErr(int code, xmlNodePtr node, const char *extra)
86
 
{
87
 
    const char *msg = NULL;
88
 
 
89
 
    switch(code) {
90
 
        case XML_TREE_INVALID_HEX:
91
 
            msg = "invalid hexadecimal character value\n";
92
 
            break;
93
 
        case XML_TREE_INVALID_DEC:
94
 
            msg = "invalid decimal character value\n";
95
 
            break;
96
 
        case XML_TREE_UNTERMINATED_ENTITY:
97
 
            msg = "unterminated entity reference %15s\n";
98
 
            break;
99
 
        case XML_TREE_NOT_UTF8:
100
 
            msg = "string is not in UTF-8\n";
101
 
            break;
102
 
        default:
103
 
            msg = "unexpected error number\n";
104
 
    }
105
 
    __xmlSimpleError(XML_FROM_TREE, code, node, msg, extra);
106
 
}
107
 
 
108
 
/************************************************************************
109
 
 *                                                                      *
110
 
 *              A few static variables and macros                       *
111
 
 *                                                                      *
112
 
 ************************************************************************/
113
 
/* #undef xmlStringText */
114
 
const xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };
115
 
/* #undef xmlStringTextNoenc */
116
 
const xmlChar xmlStringTextNoenc[] =
117
 
              { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 };
118
 
/* #undef xmlStringComment */
119
 
const xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };
120
 
 
121
 
static int xmlCompressMode = 0;
122
 
static int xmlCheckDTD = 1;
123
 
 
124
 
#define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) {              \
125
 
    xmlNodePtr ulccur = (n)->children;                                  \
126
 
    if (ulccur == NULL) {                                               \
127
 
        (n)->last = NULL;                                               \
128
 
    } else {                                                            \
129
 
        while (ulccur->next != NULL) {                                  \
130
 
                ulccur->parent = (n);                                   \
131
 
                ulccur = ulccur->next;                                  \
132
 
        }                                                               \
133
 
        ulccur->parent = (n);                                           \
134
 
        (n)->last = ulccur;                                             \
135
 
}}
136
 
 
137
 
#define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \
138
 
  (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))
139
 
 
140
 
/* #define DEBUG_BUFFER */
141
 
/* #define DEBUG_TREE */
142
 
 
143
 
/************************************************************************
144
 
 *                                                                      *
145
 
 *              Functions to move to entities.c once the                *
146
 
 *              API freeze is smoothen and they can be made public.     *
147
 
 *                                                                      *
148
 
 ************************************************************************/
149
 
#include <libxml/hash.h>
150
 
 
151
 
#ifdef LIBXML_TREE_ENABLED
152
 
/**
153
 
 * xmlGetEntityFromDtd:
154
 
 * @dtd:  A pointer to the DTD to search
155
 
 * @name:  The entity name
156
 
 *
157
 
 * Do an entity lookup in the DTD entity hash table and
158
 
 * return the corresponding entity, if found.
159
 
 *
160
 
 * Returns A pointer to the entity structure or NULL if not found.
161
 
 */
162
 
static xmlEntityPtr
163
 
xmlGetEntityFromDtd(xmlDtdPtr dtd, const xmlChar *name) {
164
 
    xmlEntitiesTablePtr table;
165
 
 
166
 
    if((dtd != NULL) && (dtd->entities != NULL)) {
167
 
        table = (xmlEntitiesTablePtr) dtd->entities;
168
 
        return((xmlEntityPtr) xmlHashLookup(table, name));
169
 
        /* return(xmlGetEntityFromTable(table, name)); */
170
 
    }
171
 
    return(NULL);
172
 
}
173
 
/**
174
 
 * xmlGetParameterEntityFromDtd:
175
 
 * @dtd:  A pointer to the DTD to search
176
 
 * @name:  The entity name
177
 
 *
178
 
 * Do an entity lookup in the DTD pararmeter entity hash table and
179
 
 * return the corresponding entity, if found.
180
 
 *
181
 
 * Returns A pointer to the entity structure or NULL if not found.
182
 
 */
183
 
static xmlEntityPtr
184
 
xmlGetParameterEntityFromDtd(xmlDtdPtr dtd, const xmlChar *name) {
185
 
    xmlEntitiesTablePtr table;
186
 
 
187
 
    if ((dtd != NULL) && (dtd->pentities != NULL)) {
188
 
        table = (xmlEntitiesTablePtr) dtd->pentities;
189
 
        return((xmlEntityPtr) xmlHashLookup(table, name));
190
 
        /* return(xmlGetEntityFromTable(table, name)); */
191
 
    }
192
 
    return(NULL);
193
 
}
194
 
#endif /* LIBXML_TREE_ENABLED */
195
 
 
196
 
/************************************************************************
197
 
 *                                                                      *
198
 
 *                      QName handling helper                           *
199
 
 *                                                                      *
200
 
 ************************************************************************/
201
 
 
202
 
/**
203
 
 * xmlBuildQName:
204
 
 * @ncname:  the Name
205
 
 * @prefix:  the prefix
206
 
 * @memory:  preallocated memory
207
 
 * @len:  preallocated memory length
208
 
 *
209
 
 * Builds the QName @prefix:@ncname in @memory if there is enough space
210
 
 * and prefix is not NULL nor empty, otherwise allocate a new string.
211
 
 * If prefix is NULL or empty it returns ncname.
212
 
 *
213
 
 * Returns the new string which must be freed by the caller if different from
214
 
 *         @memory and @ncname or NULL in case of error
215
 
 */
216
 
xmlChar *
217
 
xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix,
218
 
              xmlChar *memory, int len) {
219
 
    int lenn, lenp;
220
 
    xmlChar *ret;
221
 
 
222
 
    if (ncname == NULL) return(NULL);
223
 
    if (prefix == NULL) return((xmlChar *) ncname);
224
 
 
225
 
    lenn = strlen((char *) ncname);
226
 
    lenp = strlen((char *) prefix);
227
 
 
228
 
    if ((memory == NULL) || (len < lenn + lenp + 2)) {
229
 
        ret = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
230
 
        if (ret == NULL) {
231
 
            xmlTreeErrMemory("building QName");
232
 
            return(NULL);
233
 
        }
234
 
    } else {
235
 
        ret = memory;
236
 
    }
237
 
    memcpy(&ret[0], prefix, lenp);
238
 
    ret[lenp] = ':';
239
 
    memcpy(&ret[lenp + 1], ncname, lenn);
240
 
    ret[lenn + lenp + 1] = 0;
241
 
    return(ret);
242
 
}
243
 
 
244
 
/**
245
 
 * xmlSplitQName2:
246
 
 * @name:  the full QName
247
 
 * @prefix:  a xmlChar **
248
 
 *
249
 
 * parse an XML qualified name string
250
 
 *
251
 
 * [NS 5] QName ::= (Prefix ':')? LocalPart
252
 
 *
253
 
 * [NS 6] Prefix ::= NCName
254
 
 *
255
 
 * [NS 7] LocalPart ::= NCName
256
 
 *
257
 
 * Returns NULL if not a QName, otherwise the local part, and prefix
258
 
 *   is updated to get the Prefix if any.
259
 
 */
260
 
 
261
 
xmlChar *
262
 
xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
263
 
    int len = 0;
264
 
    xmlChar *ret = NULL;
265
 
 
266
 
    if (prefix == NULL) return(NULL);
267
 
    *prefix = NULL;
268
 
    if (name == NULL) return(NULL);
269
 
 
270
 
#ifndef XML_XML_NAMESPACE
271
 
    /* xml: prefix is not really a namespace */
272
 
    if ((name[0] == 'x') && (name[1] == 'm') &&
273
 
        (name[2] == 'l') && (name[3] == ':'))
274
 
        return(NULL);
275
 
#endif
276
 
 
277
 
    /* nasty but valid */
278
 
    if (name[0] == ':')
279
 
        return(NULL);
280
 
 
281
 
    /*
282
 
     * we are not trying to validate but just to cut, and yes it will
283
 
     * work even if this is as set of UTF-8 encoded chars
284
 
     */
285
 
    while ((name[len] != 0) && (name[len] != ':'))
286
 
        len++;
287
 
 
288
 
    if (name[len] == 0)
289
 
        return(NULL);
290
 
 
291
 
    *prefix = xmlStrndup(name, len);
292
 
    if (*prefix == NULL) {
293
 
        xmlTreeErrMemory("QName split");
294
 
        return(NULL);
295
 
    }
296
 
    ret = xmlStrdup(&name[len + 1]);
297
 
    if (ret == NULL) {
298
 
        xmlTreeErrMemory("QName split");
299
 
        if (*prefix != NULL) {
300
 
            xmlFree(*prefix);
301
 
            *prefix = NULL;
302
 
        }
303
 
        return(NULL);
304
 
    }
305
 
 
306
 
    return(ret);
307
 
}
308
 
 
309
 
/**
310
 
 * xmlSplitQName3:
311
 
 * @name:  the full QName
312
 
 * @len: an int *
313
 
 *
314
 
 * parse an XML qualified name string,i
315
 
 *
316
 
 * returns NULL if it is not a Qualified Name, otherwise, update len
317
 
 *         with the length in byte of the prefix and return a pointer
318
 
 *         to the start of the name without the prefix
319
 
 */
320
 
 
321
 
const xmlChar *
322
 
xmlSplitQName3(const xmlChar *name, int *len) {
323
 
    int l = 0;
324
 
 
325
 
    if (name == NULL) return(NULL);
326
 
    if (len == NULL) return(NULL);
327
 
 
328
 
    /* nasty but valid */
329
 
    if (name[0] == ':')
330
 
        return(NULL);
331
 
 
332
 
    /*
333
 
     * we are not trying to validate but just to cut, and yes it will
334
 
     * work even if this is as set of UTF-8 encoded chars
335
 
     */
336
 
    while ((name[l] != 0) && (name[l] != ':'))
337
 
        l++;
338
 
 
339
 
    if (name[l] == 0)
340
 
        return(NULL);
341
 
 
342
 
    *len = l;
343
 
 
344
 
    return(&name[l+1]);
345
 
}
346
 
 
347
 
/************************************************************************
348
 
 *                                                                      *
349
 
 *              Check Name, NCName and QName strings                    *
350
 
 *                                                                      *
351
 
 ************************************************************************/
352
 
 
353
 
#define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
354
 
 
355
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED)
356
 
/**
357
 
 * xmlValidateNCName:
358
 
 * @value: the value to check
359
 
 * @space: allow spaces in front and end of the string
360
 
 *
361
 
 * Check that a value conforms to the lexical space of NCName
362
 
 *
363
 
 * Returns 0 if this validates, a positive error code number otherwise
364
 
 *         and -1 in case of internal or API error.
365
 
 */
366
 
int
367
 
xmlValidateNCName(const xmlChar *value, int space) {
368
 
    const xmlChar *cur = value;
369
 
    int c,l;
370
 
 
371
 
    if (value == NULL)
372
 
        return(-1);
373
 
 
374
 
    /*
375
 
     * First quick algorithm for ASCII range
376
 
     */
377
 
    if (space)
378
 
        while (IS_BLANK_CH(*cur)) cur++;
379
 
    if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
380
 
        (*cur == '_'))
381
 
        cur++;
382
 
    else
383
 
        goto try_complex;
384
 
    while (((*cur >= 'a') && (*cur <= 'z')) ||
385
 
           ((*cur >= 'A') && (*cur <= 'Z')) ||
386
 
           ((*cur >= '0') && (*cur <= '9')) ||
387
 
           (*cur == '_') || (*cur == '-') || (*cur == '.'))
388
 
        cur++;
389
 
    if (space)
390
 
        while (IS_BLANK_CH(*cur)) cur++;
391
 
    if (*cur == 0)
392
 
        return(0);
393
 
 
394
 
try_complex:
395
 
    /*
396
 
     * Second check for chars outside the ASCII range
397
 
     */
398
 
    cur = value;
399
 
    c = CUR_SCHAR(cur, l);
400
 
    if (space) {
401
 
        while (IS_BLANK(c)) {
402
 
            cur += l;
403
 
            c = CUR_SCHAR(cur, l);
404
 
        }
405
 
    }
406
 
    if ((!IS_LETTER(c)) && (c != '_'))
407
 
        return(1);
408
 
    cur += l;
409
 
    c = CUR_SCHAR(cur, l);
410
 
    while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
411
 
           (c == '-') || (c == '_') || IS_COMBINING(c) ||
412
 
           IS_EXTENDER(c)) {
413
 
        cur += l;
414
 
        c = CUR_SCHAR(cur, l);
415
 
    }
416
 
    if (space) {
417
 
        while (IS_BLANK(c)) {
418
 
            cur += l;
419
 
            c = CUR_SCHAR(cur, l);
420
 
        }
421
 
    }
422
 
    if (c != 0)
423
 
        return(1);
424
 
 
425
 
    return(0);
426
 
}
427
 
#endif
428
 
 
429
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
430
 
/**
431
 
 * xmlValidateQName:
432
 
 * @value: the value to check
433
 
 * @space: allow spaces in front and end of the string
434
 
 *
435
 
 * Check that a value conforms to the lexical space of QName
436
 
 *
437
 
 * Returns 0 if this validates, a positive error code number otherwise
438
 
 *         and -1 in case of internal or API error.
439
 
 */
440
 
int
441
 
xmlValidateQName(const xmlChar *value, int space) {
442
 
    const xmlChar *cur = value;
443
 
    int c,l;
444
 
 
445
 
    if (value == NULL)
446
 
        return(-1);
447
 
    /*
448
 
     * First quick algorithm for ASCII range
449
 
     */
450
 
    if (space)
451
 
        while (IS_BLANK_CH(*cur)) cur++;
452
 
    if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
453
 
        (*cur == '_'))
454
 
        cur++;
455
 
    else
456
 
        goto try_complex;
457
 
    while (((*cur >= 'a') && (*cur <= 'z')) ||
458
 
           ((*cur >= 'A') && (*cur <= 'Z')) ||
459
 
           ((*cur >= '0') && (*cur <= '9')) ||
460
 
           (*cur == '_') || (*cur == '-') || (*cur == '.'))
461
 
        cur++;
462
 
    if (*cur == ':') {
463
 
        cur++;
464
 
        if (((*cur >= 'a') && (*cur <= 'z')) ||
465
 
            ((*cur >= 'A') && (*cur <= 'Z')) ||
466
 
            (*cur == '_'))
467
 
            cur++;
468
 
        else
469
 
            goto try_complex;
470
 
        while (((*cur >= 'a') && (*cur <= 'z')) ||
471
 
               ((*cur >= 'A') && (*cur <= 'Z')) ||
472
 
               ((*cur >= '0') && (*cur <= '9')) ||
473
 
               (*cur == '_') || (*cur == '-') || (*cur == '.'))
474
 
            cur++;
475
 
    }
476
 
    if (space)
477
 
        while (IS_BLANK_CH(*cur)) cur++;
478
 
    if (*cur == 0)
479
 
        return(0);
480
 
 
481
 
try_complex:
482
 
    /*
483
 
     * Second check for chars outside the ASCII range
484
 
     */
485
 
    cur = value;
486
 
    c = CUR_SCHAR(cur, l);
487
 
    if (space) {
488
 
        while (IS_BLANK(c)) {
489
 
            cur += l;
490
 
            c = CUR_SCHAR(cur, l);
491
 
        }
492
 
    }
493
 
    if ((!IS_LETTER(c)) && (c != '_'))
494
 
        return(1);
495
 
    cur += l;
496
 
    c = CUR_SCHAR(cur, l);
497
 
    while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
498
 
           (c == '-') || (c == '_') || IS_COMBINING(c) ||
499
 
           IS_EXTENDER(c)) {
500
 
        cur += l;
501
 
        c = CUR_SCHAR(cur, l);
502
 
    }
503
 
    if (c == ':') {
504
 
        cur += l;
505
 
        c = CUR_SCHAR(cur, l);
506
 
        if ((!IS_LETTER(c)) && (c != '_'))
507
 
            return(1);
508
 
        cur += l;
509
 
        c = CUR_SCHAR(cur, l);
510
 
        while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||
511
 
               (c == '-') || (c == '_') || IS_COMBINING(c) ||
512
 
               IS_EXTENDER(c)) {
513
 
            cur += l;
514
 
            c = CUR_SCHAR(cur, l);
515
 
        }
516
 
    }
517
 
    if (space) {
518
 
        while (IS_BLANK(c)) {
519
 
            cur += l;
520
 
            c = CUR_SCHAR(cur, l);
521
 
        }
522
 
    }
523
 
    if (c != 0)
524
 
        return(1);
525
 
    return(0);
526
 
}
527
 
 
528
 
/**
529
 
 * xmlValidateName:
530
 
 * @value: the value to check
531
 
 * @space: allow spaces in front and end of the string
532
 
 *
533
 
 * Check that a value conforms to the lexical space of Name
534
 
 *
535
 
 * Returns 0 if this validates, a positive error code number otherwise
536
 
 *         and -1 in case of internal or API error.
537
 
 */
538
 
int
539
 
xmlValidateName(const xmlChar *value, int space) {
540
 
    const xmlChar *cur = value;
541
 
    int c,l;
542
 
 
543
 
    if (value == NULL)
544
 
        return(-1);
545
 
    /*
546
 
     * First quick algorithm for ASCII range
547
 
     */
548
 
    if (space)
549
 
        while (IS_BLANK_CH(*cur)) cur++;
550
 
    if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||
551
 
        (*cur == '_') || (*cur == ':'))
552
 
        cur++;
553
 
    else
554
 
        goto try_complex;
555
 
    while (((*cur >= 'a') && (*cur <= 'z')) ||
556
 
           ((*cur >= 'A') && (*cur <= 'Z')) ||
557
 
           ((*cur >= '0') && (*cur <= '9')) ||
558
 
           (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
559
 
        cur++;
560
 
    if (space)
561
 
        while (IS_BLANK_CH(*cur)) cur++;
562
 
    if (*cur == 0)
563
 
        return(0);
564
 
 
565
 
try_complex:
566
 
    /*
567
 
     * Second check for chars outside the ASCII range
568
 
     */
569
 
    cur = value;
570
 
    c = CUR_SCHAR(cur, l);
571
 
    if (space) {
572
 
        while (IS_BLANK(c)) {
573
 
            cur += l;
574
 
            c = CUR_SCHAR(cur, l);
575
 
        }
576
 
    }
577
 
    if ((!IS_LETTER(c)) && (c != '_') && (c != ':'))
578
 
        return(1);
579
 
    cur += l;
580
 
    c = CUR_SCHAR(cur, l);
581
 
    while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
582
 
           (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) {
583
 
        cur += l;
584
 
        c = CUR_SCHAR(cur, l);
585
 
    }
586
 
    if (space) {
587
 
        while (IS_BLANK(c)) {
588
 
            cur += l;
589
 
            c = CUR_SCHAR(cur, l);
590
 
        }
591
 
    }
592
 
    if (c != 0)
593
 
        return(1);
594
 
    return(0);
595
 
}
596
 
 
597
 
/**
598
 
 * xmlValidateNMToken:
599
 
 * @value: the value to check
600
 
 * @space: allow spaces in front and end of the string
601
 
 *
602
 
 * Check that a value conforms to the lexical space of NMToken
603
 
 *
604
 
 * Returns 0 if this validates, a positive error code number otherwise
605
 
 *         and -1 in case of internal or API error.
606
 
 */
607
 
int
608
 
xmlValidateNMToken(const xmlChar *value, int space) {
609
 
    const xmlChar *cur = value;
610
 
    int c,l;
611
 
 
612
 
    if (value == NULL)
613
 
        return(-1);
614
 
    /*
615
 
     * First quick algorithm for ASCII range
616
 
     */
617
 
    if (space)
618
 
        while (IS_BLANK_CH(*cur)) cur++;
619
 
    if (((*cur >= 'a') && (*cur <= 'z')) ||
620
 
        ((*cur >= 'A') && (*cur <= 'Z')) ||
621
 
        ((*cur >= '0') && (*cur <= '9')) ||
622
 
        (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
623
 
        cur++;
624
 
    else
625
 
        goto try_complex;
626
 
    while (((*cur >= 'a') && (*cur <= 'z')) ||
627
 
           ((*cur >= 'A') && (*cur <= 'Z')) ||
628
 
           ((*cur >= '0') && (*cur <= '9')) ||
629
 
           (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))
630
 
        cur++;
631
 
    if (space)
632
 
        while (IS_BLANK_CH(*cur)) cur++;
633
 
    if (*cur == 0)
634
 
        return(0);
635
 
 
636
 
try_complex:
637
 
    /*
638
 
     * Second check for chars outside the ASCII range
639
 
     */
640
 
    cur = value;
641
 
    c = CUR_SCHAR(cur, l);
642
 
    if (space) {
643
 
        while (IS_BLANK(c)) {
644
 
            cur += l;
645
 
            c = CUR_SCHAR(cur, l);
646
 
        }
647
 
    }
648
 
    if (!(IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
649
 
        (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)))
650
 
        return(1);
651
 
    cur += l;
652
 
    c = CUR_SCHAR(cur, l);
653
 
    while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||
654
 
           (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) {
655
 
        cur += l;
656
 
        c = CUR_SCHAR(cur, l);
657
 
    }
658
 
    if (space) {
659
 
        while (IS_BLANK(c)) {
660
 
            cur += l;
661
 
            c = CUR_SCHAR(cur, l);
662
 
        }
663
 
    }
664
 
    if (c != 0)
665
 
        return(1);
666
 
    return(0);
667
 
}
668
 
#endif /* LIBXML_TREE_ENABLED */
669
 
 
670
 
/************************************************************************
671
 
 *                                                                      *
672
 
 *              Allocation and deallocation of basic structures         *
673
 
 *                                                                      *
674
 
 ************************************************************************/
675
 
 
676
 
/**
677
 
 * xmlSetBufferAllocationScheme:
678
 
 * @scheme:  allocation method to use
679
 
 *
680
 
 * Set the buffer allocation method.  Types are
681
 
 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
682
 
 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
683
 
 *                             improves performance
684
 
 */
685
 
void
686
 
xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) {
687
 
    if ((scheme == XML_BUFFER_ALLOC_EXACT) ||
688
 
        (scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
689
 
        (scheme == XML_BUFFER_ALLOC_HYBRID))
690
 
        xmlBufferAllocScheme = scheme;
691
 
}
692
 
 
693
 
/**
694
 
 * xmlGetBufferAllocationScheme:
695
 
 *
696
 
 * Types are
697
 
 * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down
698
 
 * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,
699
 
 *                             improves performance
700
 
 * XML_BUFFER_ALLOC_HYBRID - use exact sizes on small strings to keep memory usage tight
701
 
 *                            in normal usage, and doubleit on large strings to avoid
702
 
 *                            pathological performance.
703
 
 *
704
 
 * Returns the current allocation scheme
705
 
 */
706
 
xmlBufferAllocationScheme
707
 
xmlGetBufferAllocationScheme(void) {
708
 
    return(xmlBufferAllocScheme);
709
 
}
710
 
 
711
 
/**
712
 
 * xmlNewNs:
713
 
 * @node:  the element carrying the namespace
714
 
 * @href:  the URI associated
715
 
 * @prefix:  the prefix for the namespace
716
 
 *
717
 
 * Creation of a new Namespace. This function will refuse to create
718
 
 * a namespace with a similar prefix than an existing one present on this
719
 
 * node.
720
 
 * We use href==NULL in the case of an element creation where the namespace
721
 
 * was not defined.
722
 
 * Returns a new namespace pointer or NULL
723
 
 */
724
 
xmlNsPtr
725
 
xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
726
 
    xmlNsPtr cur;
727
 
 
728
 
    if ((node != NULL) && (node->type != XML_ELEMENT_NODE))
729
 
        return(NULL);
730
 
 
731
 
    if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
732
 
        /* xml namespace is predefined, no need to add it */
733
 
        if (xmlStrEqual(href, XML_XML_NAMESPACE))
734
 
            return(NULL);
735
 
 
736
 
        /*
737
 
         * Problem, this is an attempt to bind xml prefix to a wrong
738
 
         * namespace, which breaks
739
 
         * Namespace constraint: Reserved Prefixes and Namespace Names
740
 
         * from XML namespace. But documents authors may not care in
741
 
         * their context so let's proceed.
742
 
         */
743
 
    }
744
 
 
745
 
    /*
746
 
     * Allocate a new Namespace and fill the fields.
747
 
     */
748
 
    cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
749
 
    if (cur == NULL) {
750
 
        xmlTreeErrMemory("building namespace");
751
 
        return(NULL);
752
 
    }
753
 
    memset(cur, 0, sizeof(xmlNs));
754
 
    cur->type = XML_LOCAL_NAMESPACE;
755
 
 
756
 
    if (href != NULL)
757
 
        cur->href = xmlStrdup(href);
758
 
    if (prefix != NULL)
759
 
        cur->prefix = xmlStrdup(prefix);
760
 
 
761
 
    /*
762
 
     * Add it at the end to preserve parsing order ...
763
 
     * and checks for existing use of the prefix
764
 
     */
765
 
    if (node != NULL) {
766
 
        if (node->nsDef == NULL) {
767
 
            node->nsDef = cur;
768
 
        } else {
769
 
            xmlNsPtr prev = node->nsDef;
770
 
 
771
 
            if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
772
 
                (xmlStrEqual(prev->prefix, cur->prefix))) {
773
 
                xmlFreeNs(cur);
774
 
                return(NULL);
775
 
            }
776
 
            while (prev->next != NULL) {
777
 
                prev = prev->next;
778
 
                if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
779
 
                    (xmlStrEqual(prev->prefix, cur->prefix))) {
780
 
                    xmlFreeNs(cur);
781
 
                    return(NULL);
782
 
                }
783
 
            }
784
 
            prev->next = cur;
785
 
        }
786
 
    }
787
 
    return(cur);
788
 
}
789
 
 
790
 
/**
791
 
 * xmlSetNs:
792
 
 * @node:  a node in the document
793
 
 * @ns:  a namespace pointer
794
 
 *
795
 
 * Associate a namespace to a node, a posteriori.
796
 
 */
797
 
void
798
 
xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
799
 
    if (node == NULL) {
800
 
#ifdef DEBUG_TREE
801
 
        xmlGenericError(xmlGenericErrorContext,
802
 
                "xmlSetNs: node == NULL\n");
803
 
#endif
804
 
        return;
805
 
    }
806
 
    node->ns = ns;
807
 
}
808
 
 
809
 
/**
810
 
 * xmlFreeNs:
811
 
 * @cur:  the namespace pointer
812
 
 *
813
 
 * Free up the structures associated to a namespace
814
 
 */
815
 
void
816
 
xmlFreeNs(xmlNsPtr cur) {
817
 
    if (cur == NULL) {
818
 
#ifdef DEBUG_TREE
819
 
        xmlGenericError(xmlGenericErrorContext,
820
 
                "xmlFreeNs : ns == NULL\n");
821
 
#endif
822
 
        return;
823
 
    }
824
 
    if (cur->href != NULL) xmlFree((char *) cur->href);
825
 
    if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
826
 
    xmlFree(cur);
827
 
}
828
 
 
829
 
/**
830
 
 * xmlFreeNsList:
831
 
 * @cur:  the first namespace pointer
832
 
 *
833
 
 * Free up all the structures associated to the chained namespaces.
834
 
 */
835
 
void
836
 
xmlFreeNsList(xmlNsPtr cur) {
837
 
    xmlNsPtr next;
838
 
    if (cur == NULL) {
839
 
#ifdef DEBUG_TREE
840
 
        xmlGenericError(xmlGenericErrorContext,
841
 
                "xmlFreeNsList : ns == NULL\n");
842
 
#endif
843
 
        return;
844
 
    }
845
 
    while (cur != NULL) {
846
 
        next = cur->next;
847
 
        xmlFreeNs(cur);
848
 
        cur = next;
849
 
    }
850
 
}
851
 
 
852
 
/**
853
 
 * xmlNewDtd:
854
 
 * @doc:  the document pointer
855
 
 * @name:  the DTD name
856
 
 * @ExternalID:  the external ID
857
 
 * @SystemID:  the system ID
858
 
 *
859
 
 * Creation of a new DTD for the external subset. To create an
860
 
 * internal subset, use xmlCreateIntSubset().
861
 
 *
862
 
 * Returns a pointer to the new DTD structure
863
 
 */
864
 
xmlDtdPtr
865
 
xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
866
 
                    const xmlChar *ExternalID, const xmlChar *SystemID) {
867
 
    xmlDtdPtr cur;
868
 
 
869
 
    if ((doc != NULL) && (doc->extSubset != NULL)) {
870
 
#ifdef DEBUG_TREE
871
 
        xmlGenericError(xmlGenericErrorContext,
872
 
                "xmlNewDtd(%s): document %s already have a DTD %s\n",
873
 
            /* !!! */ (char *) name, doc->name,
874
 
            /* !!! */ (char *)doc->extSubset->name);
875
 
#endif
876
 
        return(NULL);
877
 
    }
878
 
 
879
 
    /*
880
 
     * Allocate a new DTD and fill the fields.
881
 
     */
882
 
    cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
883
 
    if (cur == NULL) {
884
 
        xmlTreeErrMemory("building DTD");
885
 
        return(NULL);
886
 
    }
887
 
    memset(cur, 0 , sizeof(xmlDtd));
888
 
    cur->type = XML_DTD_NODE;
889
 
 
890
 
    if (name != NULL)
891
 
        cur->name = xmlStrdup(name);
892
 
    if (ExternalID != NULL)
893
 
        cur->ExternalID = xmlStrdup(ExternalID);
894
 
    if (SystemID != NULL)
895
 
        cur->SystemID = xmlStrdup(SystemID);
896
 
    if (doc != NULL)
897
 
        doc->extSubset = cur;
898
 
    cur->doc = doc;
899
 
 
900
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
901
 
        xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
902
 
    return(cur);
903
 
}
904
 
 
905
 
/**
906
 
 * xmlGetIntSubset:
907
 
 * @doc:  the document pointer
908
 
 *
909
 
 * Get the internal subset of a document
910
 
 * Returns a pointer to the DTD structure or NULL if not found
911
 
 */
912
 
 
913
 
xmlDtdPtr
914
 
xmlGetIntSubset(xmlDocPtr doc) {
915
 
    xmlNodePtr cur;
916
 
 
917
 
    if (doc == NULL)
918
 
        return(NULL);
919
 
    cur = doc->children;
920
 
    while (cur != NULL) {
921
 
        if (cur->type == XML_DTD_NODE)
922
 
            return((xmlDtdPtr) cur);
923
 
        cur = cur->next;
924
 
    }
925
 
    return((xmlDtdPtr) doc->intSubset);
926
 
}
927
 
 
928
 
/**
929
 
 * xmlCreateIntSubset:
930
 
 * @doc:  the document pointer
931
 
 * @name:  the DTD name
932
 
 * @ExternalID:  the external (PUBLIC) ID
933
 
 * @SystemID:  the system ID
934
 
 *
935
 
 * Create the internal subset of a document
936
 
 * Returns a pointer to the new DTD structure
937
 
 */
938
 
xmlDtdPtr
939
 
xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
940
 
                   const xmlChar *ExternalID, const xmlChar *SystemID) {
941
 
    xmlDtdPtr cur;
942
 
 
943
 
    if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) {
944
 
#ifdef DEBUG_TREE
945
 
        xmlGenericError(xmlGenericErrorContext,
946
 
 
947
 
     "xmlCreateIntSubset(): document %s already have an internal subset\n",
948
 
            doc->name);
949
 
#endif
950
 
        return(NULL);
951
 
    }
952
 
 
953
 
    /*
954
 
     * Allocate a new DTD and fill the fields.
955
 
     */
956
 
    cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
957
 
    if (cur == NULL) {
958
 
        xmlTreeErrMemory("building internal subset");
959
 
        return(NULL);
960
 
    }
961
 
    memset(cur, 0, sizeof(xmlDtd));
962
 
    cur->type = XML_DTD_NODE;
963
 
 
964
 
    if (name != NULL) {
965
 
        cur->name = xmlStrdup(name);
966
 
        if (cur->name == NULL) {
967
 
            xmlTreeErrMemory("building internal subset");
968
 
            xmlFree(cur);
969
 
            return(NULL);
970
 
        }
971
 
    }
972
 
    if (ExternalID != NULL) {
973
 
        cur->ExternalID = xmlStrdup(ExternalID);
974
 
        if (cur->ExternalID  == NULL) {
975
 
            xmlTreeErrMemory("building internal subset");
976
 
            if (cur->name != NULL)
977
 
                xmlFree((char *)cur->name);
978
 
            xmlFree(cur);
979
 
            return(NULL);
980
 
        }
981
 
    }
982
 
    if (SystemID != NULL) {
983
 
        cur->SystemID = xmlStrdup(SystemID);
984
 
        if (cur->SystemID == NULL) {
985
 
            xmlTreeErrMemory("building internal subset");
986
 
            if (cur->name != NULL)
987
 
                xmlFree((char *)cur->name);
988
 
            if (cur->ExternalID != NULL)
989
 
                xmlFree((char *)cur->ExternalID);
990
 
            xmlFree(cur);
991
 
            return(NULL);
992
 
        }
993
 
    }
994
 
    if (doc != NULL) {
995
 
        doc->intSubset = cur;
996
 
        cur->parent = doc;
997
 
        cur->doc = doc;
998
 
        if (doc->children == NULL) {
999
 
            doc->children = (xmlNodePtr) cur;
1000
 
            doc->last = (xmlNodePtr) cur;
1001
 
        } else {
1002
 
            if (doc->type == XML_HTML_DOCUMENT_NODE) {
1003
 
                xmlNodePtr prev;
1004
 
 
1005
 
                prev = doc->children;
1006
 
                prev->prev = (xmlNodePtr) cur;
1007
 
                cur->next = prev;
1008
 
                doc->children = (xmlNodePtr) cur;
1009
 
            } else {
1010
 
                xmlNodePtr next;
1011
 
 
1012
 
                next = doc->children;
1013
 
                while ((next != NULL) && (next->type != XML_ELEMENT_NODE))
1014
 
                    next = next->next;
1015
 
                if (next == NULL) {
1016
 
                    cur->prev = doc->last;
1017
 
                    cur->prev->next = (xmlNodePtr) cur;
1018
 
                    cur->next = NULL;
1019
 
                    doc->last = (xmlNodePtr) cur;
1020
 
                } else {
1021
 
                    cur->next = next;
1022
 
                    cur->prev = next->prev;
1023
 
                    if (cur->prev == NULL)
1024
 
                        doc->children = (xmlNodePtr) cur;
1025
 
                    else
1026
 
                        cur->prev->next = (xmlNodePtr) cur;
1027
 
                    next->prev = (xmlNodePtr) cur;
1028
 
                }
1029
 
            }
1030
 
        }
1031
 
    }
1032
 
 
1033
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1034
 
        xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
1035
 
    return(cur);
1036
 
}
1037
 
 
1038
 
/**
1039
 
 * DICT_FREE:
1040
 
 * @str:  a string
1041
 
 *
1042
 
 * Free a string if it is not owned by the "dict" dictionnary in the
1043
 
 * current scope
1044
 
 */
1045
 
#define DICT_FREE(str)                                          \
1046
 
        if ((str) && ((!dict) ||                                \
1047
 
            (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
1048
 
            xmlFree((char *)(str));
1049
 
 
1050
 
 
1051
 
/**
1052
 
 * DICT_COPY:
1053
 
 * @str:  a string
1054
 
 *
1055
 
 * Copy a string using a "dict" dictionnary in the current scope,
1056
 
 * if availabe.
1057
 
 */
1058
 
#define DICT_COPY(str, cpy) \
1059
 
    if (str) { \
1060
 
        if (dict) { \
1061
 
            if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1062
 
                cpy = (xmlChar *) (str); \
1063
 
            else \
1064
 
                cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1065
 
        } else \
1066
 
            cpy = xmlStrdup((const xmlChar *)(str)); }
1067
 
 
1068
 
/**
1069
 
 * DICT_CONST_COPY:
1070
 
 * @str:  a string
1071
 
 *
1072
 
 * Copy a string using a "dict" dictionnary in the current scope,
1073
 
 * if availabe.
1074
 
 */
1075
 
#define DICT_CONST_COPY(str, cpy) \
1076
 
    if (str) { \
1077
 
        if (dict) { \
1078
 
            if (xmlDictOwns(dict, (const xmlChar *)(str))) \
1079
 
                cpy = (const xmlChar *) (str); \
1080
 
            else \
1081
 
                cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \
1082
 
        } else \
1083
 
            cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }
1084
 
 
1085
 
 
1086
 
/**
1087
 
 * xmlFreeDtd:
1088
 
 * @cur:  the DTD structure to free up
1089
 
 *
1090
 
 * Free a DTD structure.
1091
 
 */
1092
 
void
1093
 
xmlFreeDtd(xmlDtdPtr cur) {
1094
 
    xmlDictPtr dict = NULL;
1095
 
 
1096
 
    if (cur == NULL) {
1097
 
        return;
1098
 
    }
1099
 
    if (cur->doc != NULL) dict = cur->doc->dict;
1100
 
 
1101
 
    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
1102
 
        xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
1103
 
 
1104
 
    if (cur->children != NULL) {
1105
 
        xmlNodePtr next, c = cur->children;
1106
 
 
1107
 
        /*
1108
 
         * Cleanup all nodes which are not part of the specific lists
1109
 
         * of notations, elements, attributes and entities.
1110
 
         */
1111
 
        while (c != NULL) {
1112
 
            next = c->next;
1113
 
            if ((c->type != XML_NOTATION_NODE) &&
1114
 
                (c->type != XML_ELEMENT_DECL) &&
1115
 
                (c->type != XML_ATTRIBUTE_DECL) &&
1116
 
                (c->type != XML_ENTITY_DECL)) {
1117
 
                xmlUnlinkNode(c);
1118
 
                xmlFreeNode(c);
1119
 
            }
1120
 
            c = next;
1121
 
        }
1122
 
    }
1123
 
    DICT_FREE(cur->name)
1124
 
    DICT_FREE(cur->SystemID)
1125
 
    DICT_FREE(cur->ExternalID)
1126
 
    /* TODO !!! */
1127
 
    if (cur->notations != NULL)
1128
 
        xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
1129
 
 
1130
 
    if (cur->elements != NULL)
1131
 
        xmlFreeElementTable((xmlElementTablePtr) cur->elements);
1132
 
    if (cur->attributes != NULL)
1133
 
        xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
1134
 
    if (cur->entities != NULL)
1135
 
        xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
1136
 
    if (cur->pentities != NULL)
1137
 
        xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->pentities);
1138
 
 
1139
 
    xmlFree(cur);
1140
 
}
1141
 
 
1142
 
/**
1143
 
 * xmlNewDoc:
1144
 
 * @version:  xmlChar string giving the version of XML "1.0"
1145
 
 *
1146
 
 * Creates a new XML document
1147
 
 *
1148
 
 * Returns a new document
1149
 
 */
1150
 
xmlDocPtr
1151
 
xmlNewDoc(const xmlChar *version) {
1152
 
    xmlDocPtr cur;
1153
 
 
1154
 
    if (version == NULL)
1155
 
        version = (const xmlChar *) "1.0";
1156
 
 
1157
 
    /*
1158
 
     * Allocate a new document and fill the fields.
1159
 
     */
1160
 
    cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
1161
 
    if (cur == NULL) {
1162
 
        xmlTreeErrMemory("building doc");
1163
 
        return(NULL);
1164
 
    }
1165
 
    memset(cur, 0, sizeof(xmlDoc));
1166
 
    cur->type = XML_DOCUMENT_NODE;
1167
 
 
1168
 
    cur->version = xmlStrdup(version);
1169
 
    if (cur->version == NULL) {
1170
 
        xmlTreeErrMemory("building doc");
1171
 
        xmlFree(cur);
1172
 
        return(NULL);
1173
 
    }
1174
 
    cur->standalone = -1;
1175
 
    cur->compression = -1; /* not initialized */
1176
 
    cur->doc = cur;
1177
 
    cur->parseFlags = 0;
1178
 
    cur->properties = XML_DOC_USERBUILT;
1179
 
    /*
1180
 
     * The in memory encoding is always UTF8
1181
 
     * This field will never change and would
1182
 
     * be obsolete if not for binary compatibility.
1183
 
     */
1184
 
    cur->charset = XML_CHAR_ENCODING_UTF8;
1185
 
 
1186
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1187
 
        xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
1188
 
    return(cur);
1189
 
}
1190
 
 
1191
 
/**
1192
 
 * xmlFreeDoc:
1193
 
 * @cur:  pointer to the document
1194
 
 *
1195
 
 * Free up all the structures used by a document, tree included.
1196
 
 */
1197
 
void
1198
 
xmlFreeDoc(xmlDocPtr cur) {
1199
 
    xmlDtdPtr extSubset, intSubset;
1200
 
    xmlDictPtr dict = NULL;
1201
 
 
1202
 
    if (cur == NULL) {
1203
 
#ifdef DEBUG_TREE
1204
 
        xmlGenericError(xmlGenericErrorContext,
1205
 
                "xmlFreeDoc : document == NULL\n");
1206
 
#endif
1207
 
        return;
1208
 
    }
1209
 
#ifdef LIBXML_DEBUG_RUNTIME
1210
 
#ifdef LIBXML_DEBUG_ENABLED
1211
 
    xmlDebugCheckDocument(stderr, cur);
1212
 
#endif
1213
 
#endif
1214
 
 
1215
 
    if (cur != NULL) dict = cur->dict;
1216
 
 
1217
 
    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
1218
 
        xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
1219
 
 
1220
 
    /*
1221
 
     * Do this before freeing the children list to avoid ID lookups
1222
 
     */
1223
 
    if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
1224
 
    cur->ids = NULL;
1225
 
    if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
1226
 
    cur->refs = NULL;
1227
 
    extSubset = cur->extSubset;
1228
 
    intSubset = cur->intSubset;
1229
 
    if (intSubset == extSubset)
1230
 
        extSubset = NULL;
1231
 
    if (extSubset != NULL) {
1232
 
        xmlUnlinkNode((xmlNodePtr) cur->extSubset);
1233
 
        cur->extSubset = NULL;
1234
 
        xmlFreeDtd(extSubset);
1235
 
    }
1236
 
    if (intSubset != NULL) {
1237
 
        xmlUnlinkNode((xmlNodePtr) cur->intSubset);
1238
 
        cur->intSubset = NULL;
1239
 
        xmlFreeDtd(intSubset);
1240
 
    }
1241
 
 
1242
 
    if (cur->children != NULL) xmlFreeNodeList(cur->children);
1243
 
    if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
1244
 
 
1245
 
    DICT_FREE(cur->version)
1246
 
    DICT_FREE(cur->name)
1247
 
    DICT_FREE(cur->encoding)
1248
 
    DICT_FREE(cur->URL)
1249
 
    xmlFree(cur);
1250
 
    if (dict) xmlDictFree(dict);
1251
 
}
1252
 
 
1253
 
/**
1254
 
 * xmlStringLenGetNodeList:
1255
 
 * @doc:  the document
1256
 
 * @value:  the value of the text
1257
 
 * @len:  the length of the string value
1258
 
 *
1259
 
 * Parse the value string and build the node list associated. Should
1260
 
 * produce a flat tree with only TEXTs and ENTITY_REFs.
1261
 
 * Returns a pointer to the first child
1262
 
 */
1263
 
xmlNodePtr
1264
 
xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
1265
 
    xmlNodePtr ret = NULL, last = NULL;
1266
 
    xmlNodePtr node;
1267
 
    xmlChar *val;
1268
 
    const xmlChar *cur = value, *end = cur + len;
1269
 
    const xmlChar *q;
1270
 
    xmlEntityPtr ent;
1271
 
    xmlBufPtr buf;
1272
 
 
1273
 
    if (value == NULL) return(NULL);
1274
 
 
1275
 
    buf = xmlBufCreateSize(0);
1276
 
    if (buf == NULL) return(NULL);
1277
 
    xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_HYBRID);
1278
 
 
1279
 
    q = cur;
1280
 
    while ((cur < end) && (*cur != 0)) {
1281
 
        if (cur[0] == '&') {
1282
 
            int charval = 0;
1283
 
            xmlChar tmp;
1284
 
 
1285
 
            /*
1286
 
             * Save the current text.
1287
 
             */
1288
 
            if (cur != q) {
1289
 
                if (xmlBufAdd(buf, q, cur - q))
1290
 
                    goto out;
1291
 
            }
1292
 
            q = cur;
1293
 
            if ((cur + 2 < end) && (cur[1] == '#') && (cur[2] == 'x')) {
1294
 
                cur += 3;
1295
 
                if (cur < end)
1296
 
                    tmp = *cur;
1297
 
                else
1298
 
                    tmp = 0;
1299
 
                while (tmp != ';') { /* Non input consuming loop */
1300
 
                    if ((tmp >= '0') && (tmp <= '9'))
1301
 
                        charval = charval * 16 + (tmp - '0');
1302
 
                    else if ((tmp >= 'a') && (tmp <= 'f'))
1303
 
                        charval = charval * 16 + (tmp - 'a') + 10;
1304
 
                    else if ((tmp >= 'A') && (tmp <= 'F'))
1305
 
                        charval = charval * 16 + (tmp - 'A') + 10;
1306
 
                    else {
1307
 
                        xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
1308
 
                                   NULL);
1309
 
                        charval = 0;
1310
 
                        break;
1311
 
                    }
1312
 
                    cur++;
1313
 
                    if (cur < end)
1314
 
                        tmp = *cur;
1315
 
                    else
1316
 
                        tmp = 0;
1317
 
                }
1318
 
                if (tmp == ';')
1319
 
                    cur++;
1320
 
                q = cur;
1321
 
            } else if ((cur + 1 < end) && (cur[1] == '#')) {
1322
 
                cur += 2;
1323
 
                if (cur < end)
1324
 
                    tmp = *cur;
1325
 
                else
1326
 
                    tmp = 0;
1327
 
                while (tmp != ';') { /* Non input consuming loops */
1328
 
                    if ((tmp >= '0') && (tmp <= '9'))
1329
 
                        charval = charval * 10 + (tmp - '0');
1330
 
                    else {
1331
 
                        xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
1332
 
                                   NULL);
1333
 
                        charval = 0;
1334
 
                        break;
1335
 
                    }
1336
 
                    cur++;
1337
 
                    if (cur < end)
1338
 
                        tmp = *cur;
1339
 
                    else
1340
 
                        tmp = 0;
1341
 
                }
1342
 
                if (tmp == ';')
1343
 
                    cur++;
1344
 
                q = cur;
1345
 
            } else {
1346
 
                /*
1347
 
                 * Read the entity string
1348
 
                 */
1349
 
                cur++;
1350
 
                q = cur;
1351
 
                while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++;
1352
 
                if ((cur >= end) || (*cur == 0)) {
1353
 
                    xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, (xmlNodePtr) doc,
1354
 
                               (const char *) q);
1355
 
                    goto out;
1356
 
                }
1357
 
                if (cur != q) {
1358
 
                    /*
1359
 
                     * Predefined entities don't generate nodes
1360
 
                     */
1361
 
                    val = xmlStrndup(q, cur - q);
1362
 
                    ent = xmlGetDocEntity(doc, val);
1363
 
                    if ((ent != NULL) &&
1364
 
                        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1365
 
 
1366
 
                        if (xmlBufCat(buf, ent->content))
1367
 
                            goto out;
1368
 
 
1369
 
                    } else {
1370
 
                        /*
1371
 
                         * Flush buffer so far
1372
 
                         */
1373
 
                        if (!xmlBufIsEmpty(buf)) {
1374
 
                            node = xmlNewDocText(doc, NULL);
1375
 
                            if (node == NULL) {
1376
 
                                if (val != NULL) xmlFree(val);
1377
 
                                goto out;
1378
 
                            }
1379
 
                            node->content = xmlBufDetach(buf);
1380
 
 
1381
 
                            if (last == NULL) {
1382
 
                                last = ret = node;
1383
 
                            } else {
1384
 
                                last = xmlAddNextSibling(last, node);
1385
 
                            }
1386
 
                        }
1387
 
 
1388
 
                        /*
1389
 
                         * Create a new REFERENCE_REF node
1390
 
                         */
1391
 
                        node = xmlNewReference(doc, val);
1392
 
                        if (node == NULL) {
1393
 
                            if (val != NULL) xmlFree(val);
1394
 
                            goto out;
1395
 
                        }
1396
 
                        else if ((ent != NULL) && (ent->children == NULL)) {
1397
 
                            xmlNodePtr temp;
1398
 
 
1399
 
                            ent->children = xmlStringGetNodeList(doc,
1400
 
                                    (const xmlChar*)node->content);
1401
 
                            ent->owner = 1;
1402
 
                            temp = ent->children;
1403
 
                            while (temp) {
1404
 
                                temp->parent = (xmlNodePtr)ent;
1405
 
                                ent->last = temp;
1406
 
                                temp = temp->next;
1407
 
                            }
1408
 
                        }
1409
 
                        if (last == NULL) {
1410
 
                            last = ret = node;
1411
 
                        } else {
1412
 
                            last = xmlAddNextSibling(last, node);
1413
 
                        }
1414
 
                    }
1415
 
                    xmlFree(val);
1416
 
                }
1417
 
                cur++;
1418
 
                q = cur;
1419
 
            }
1420
 
            if (charval != 0) {
1421
 
                xmlChar buffer[10];
1422
 
                int l;
1423
 
 
1424
 
                l = xmlCopyCharMultiByte(buffer, charval);
1425
 
                buffer[l] = 0;
1426
 
 
1427
 
                if (xmlBufCat(buf, buffer))
1428
 
                    goto out;
1429
 
                charval = 0;
1430
 
            }
1431
 
        } else
1432
 
            cur++;
1433
 
    }
1434
 
 
1435
 
    if (cur != q) {
1436
 
        /*
1437
 
         * Handle the last piece of text.
1438
 
         */
1439
 
        if (xmlBufAdd(buf, q, cur - q))
1440
 
            goto out;
1441
 
    }
1442
 
 
1443
 
    if (!xmlBufIsEmpty(buf)) {
1444
 
        node = xmlNewDocText(doc, NULL);
1445
 
        if (node == NULL) goto out;
1446
 
        node->content = xmlBufDetach(buf);
1447
 
 
1448
 
        if (last == NULL) {
1449
 
            last = ret = node;
1450
 
        } else {
1451
 
            last = xmlAddNextSibling(last, node);
1452
 
        }
1453
 
    } else if (ret == NULL) {
1454
 
        ret = xmlNewDocText(doc, BAD_CAST "");
1455
 
    }
1456
 
 
1457
 
out:
1458
 
    xmlBufFree(buf);
1459
 
    return(ret);
1460
 
}
1461
 
 
1462
 
/**
1463
 
 * xmlStringGetNodeList:
1464
 
 * @doc:  the document
1465
 
 * @value:  the value of the attribute
1466
 
 *
1467
 
 * Parse the value string and build the node list associated. Should
1468
 
 * produce a flat tree with only TEXTs and ENTITY_REFs.
1469
 
 * Returns a pointer to the first child
1470
 
 */
1471
 
xmlNodePtr
1472
 
xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
1473
 
    xmlNodePtr ret = NULL, last = NULL;
1474
 
    xmlNodePtr node;
1475
 
    xmlChar *val;
1476
 
    const xmlChar *cur = value;
1477
 
    const xmlChar *q;
1478
 
    xmlEntityPtr ent;
1479
 
    xmlBufPtr buf;
1480
 
 
1481
 
    if (value == NULL) return(NULL);
1482
 
 
1483
 
    buf = xmlBufCreateSize(0);
1484
 
    if (buf == NULL) return(NULL);
1485
 
    xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_HYBRID);
1486
 
 
1487
 
    q = cur;
1488
 
    while (*cur != 0) {
1489
 
        if (cur[0] == '&') {
1490
 
            int charval = 0;
1491
 
            xmlChar tmp;
1492
 
 
1493
 
            /*
1494
 
             * Save the current text.
1495
 
             */
1496
 
            if (cur != q) {
1497
 
                if (xmlBufAdd(buf, q, cur - q))
1498
 
                    goto out;
1499
 
            }
1500
 
            q = cur;
1501
 
            if ((cur[1] == '#') && (cur[2] == 'x')) {
1502
 
                cur += 3;
1503
 
                tmp = *cur;
1504
 
                while (tmp != ';') { /* Non input consuming loop */
1505
 
                    if ((tmp >= '0') && (tmp <= '9'))
1506
 
                        charval = charval * 16 + (tmp - '0');
1507
 
                    else if ((tmp >= 'a') && (tmp <= 'f'))
1508
 
                        charval = charval * 16 + (tmp - 'a') + 10;
1509
 
                    else if ((tmp >= 'A') && (tmp <= 'F'))
1510
 
                        charval = charval * 16 + (tmp - 'A') + 10;
1511
 
                    else {
1512
 
                        xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
1513
 
                                   NULL);
1514
 
                        charval = 0;
1515
 
                        break;
1516
 
                    }
1517
 
                    cur++;
1518
 
                    tmp = *cur;
1519
 
                }
1520
 
                if (tmp == ';')
1521
 
                    cur++;
1522
 
                q = cur;
1523
 
            } else if  (cur[1] == '#') {
1524
 
                cur += 2;
1525
 
                tmp = *cur;
1526
 
                while (tmp != ';') { /* Non input consuming loops */
1527
 
                    if ((tmp >= '0') && (tmp <= '9'))
1528
 
                        charval = charval * 10 + (tmp - '0');
1529
 
                    else {
1530
 
                        xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
1531
 
                                   NULL);
1532
 
                        charval = 0;
1533
 
                        break;
1534
 
                    }
1535
 
                    cur++;
1536
 
                    tmp = *cur;
1537
 
                }
1538
 
                if (tmp == ';')
1539
 
                    cur++;
1540
 
                q = cur;
1541
 
            } else {
1542
 
                /*
1543
 
                 * Read the entity string
1544
 
                 */
1545
 
                cur++;
1546
 
                q = cur;
1547
 
                while ((*cur != 0) && (*cur != ';')) cur++;
1548
 
                if (*cur == 0) {
1549
 
                    xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY,
1550
 
                               (xmlNodePtr) doc, (const char *) q);
1551
 
                    goto out;
1552
 
                }
1553
 
                if (cur != q) {
1554
 
                    /*
1555
 
                     * Predefined entities don't generate nodes
1556
 
                     */
1557
 
                    val = xmlStrndup(q, cur - q);
1558
 
                    ent = xmlGetDocEntity(doc, val);
1559
 
                    if ((ent != NULL) &&
1560
 
                        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
1561
 
 
1562
 
                        if (xmlBufCat(buf, ent->content))
1563
 
                            goto out;
1564
 
 
1565
 
                    } else {
1566
 
                        /*
1567
 
                         * Flush buffer so far
1568
 
                         */
1569
 
                        if (!xmlBufIsEmpty(buf)) {
1570
 
                            node = xmlNewDocText(doc, NULL);
1571
 
                            node->content = xmlBufDetach(buf);
1572
 
 
1573
 
                            if (last == NULL) {
1574
 
                                last = ret = node;
1575
 
                            } else {
1576
 
                                last = xmlAddNextSibling(last, node);
1577
 
                            }
1578
 
                        }
1579
 
 
1580
 
                        /*
1581
 
                         * Create a new REFERENCE_REF node
1582
 
                         */
1583
 
                        node = xmlNewReference(doc, val);
1584
 
                        if (node == NULL) {
1585
 
                            if (val != NULL) xmlFree(val);
1586
 
                            goto out;
1587
 
                        }
1588
 
                        else if ((ent != NULL) && (ent->children == NULL)) {
1589
 
                            xmlNodePtr temp;
1590
 
 
1591
 
                            ent->children = xmlStringGetNodeList(doc,
1592
 
                                    (const xmlChar*)node->content);
1593
 
                            ent->owner = 1;
1594
 
                            temp = ent->children;
1595
 
                            while (temp) {
1596
 
                                temp->parent = (xmlNodePtr)ent;
1597
 
                                temp = temp->next;
1598
 
                            }
1599
 
                        }
1600
 
                        if (last == NULL) {
1601
 
                            last = ret = node;
1602
 
                        } else {
1603
 
                            last = xmlAddNextSibling(last, node);
1604
 
                        }
1605
 
                    }
1606
 
                    xmlFree(val);
1607
 
                }
1608
 
                cur++;
1609
 
                q = cur;
1610
 
            }
1611
 
            if (charval != 0) {
1612
 
                xmlChar buffer[10];
1613
 
                int len;
1614
 
 
1615
 
                len = xmlCopyCharMultiByte(buffer, charval);
1616
 
                buffer[len] = 0;
1617
 
 
1618
 
                if (xmlBufCat(buf, buffer))
1619
 
                    goto out;
1620
 
                charval = 0;
1621
 
            }
1622
 
        } else
1623
 
            cur++;
1624
 
    }
1625
 
    if ((cur != q) || (ret == NULL)) {
1626
 
        /*
1627
 
         * Handle the last piece of text.
1628
 
         */
1629
 
        xmlBufAdd(buf, q, cur - q);
1630
 
    }
1631
 
 
1632
 
    if (!xmlBufIsEmpty(buf)) {
1633
 
        node = xmlNewDocText(doc, NULL);
1634
 
        node->content = xmlBufDetach(buf);
1635
 
 
1636
 
        if (last == NULL) {
1637
 
            last = ret = node;
1638
 
        } else {
1639
 
            last = xmlAddNextSibling(last, node);
1640
 
        }
1641
 
    }
1642
 
 
1643
 
out:
1644
 
    xmlBufFree(buf);
1645
 
    return(ret);
1646
 
}
1647
 
 
1648
 
/**
1649
 
 * xmlNodeListGetString:
1650
 
 * @doc:  the document
1651
 
 * @list:  a Node list
1652
 
 * @inLine:  should we replace entity contents or show their external form
1653
 
 *
1654
 
 * Build the string equivalent to the text contained in the Node list
1655
 
 * made of TEXTs and ENTITY_REFs
1656
 
 *
1657
 
 * Returns a pointer to the string copy, the caller must free it with xmlFree().
1658
 
 */
1659
 
xmlChar *
1660
 
xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine)
1661
 
{
1662
 
    xmlNodePtr node = list;
1663
 
    xmlChar *ret = NULL;
1664
 
    xmlEntityPtr ent;
1665
 
    int attr;
1666
 
 
1667
 
    if (list == NULL)
1668
 
        return (NULL);
1669
 
    if ((list->parent != NULL) && (list->parent->type == XML_ATTRIBUTE_NODE))
1670
 
        attr = 1;
1671
 
    else
1672
 
        attr = 0;
1673
 
 
1674
 
    while (node != NULL) {
1675
 
        if ((node->type == XML_TEXT_NODE) ||
1676
 
            (node->type == XML_CDATA_SECTION_NODE)) {
1677
 
            if (inLine) {
1678
 
                ret = xmlStrcat(ret, node->content);
1679
 
            } else {
1680
 
                xmlChar *buffer;
1681
 
 
1682
 
                if (attr)
1683
 
                    buffer = xmlEncodeAttributeEntities(doc, node->content);
1684
 
                else
1685
 
                    buffer = xmlEncodeEntitiesReentrant(doc, node->content);
1686
 
                if (buffer != NULL) {
1687
 
                    ret = xmlStrcat(ret, buffer);
1688
 
                    xmlFree(buffer);
1689
 
                }
1690
 
            }
1691
 
        } else if (node->type == XML_ENTITY_REF_NODE) {
1692
 
            if (inLine) {
1693
 
                ent = xmlGetDocEntity(doc, node->name);
1694
 
                if (ent != NULL) {
1695
 
                    xmlChar *buffer;
1696
 
 
1697
 
                    /* an entity content can be any "well balanced chunk",
1698
 
                     * i.e. the result of the content [43] production:
1699
 
                     * http://www.w3.org/TR/REC-xml#NT-content.
1700
 
                     * So it can contain text, CDATA section or nested
1701
 
                     * entity reference nodes (among others).
1702
 
                     * -> we recursive  call xmlNodeListGetString()
1703
 
                     * which handles these types */
1704
 
                    buffer = xmlNodeListGetString(doc, ent->children, 1);
1705
 
                    if (buffer != NULL) {
1706
 
                        ret = xmlStrcat(ret, buffer);
1707
 
                        xmlFree(buffer);
1708
 
                    }
1709
 
                } else {
1710
 
                    ret = xmlStrcat(ret, node->content);
1711
 
                }
1712
 
            } else {
1713
 
                xmlChar buf[2];
1714
 
 
1715
 
                buf[0] = '&';
1716
 
                buf[1] = 0;
1717
 
                ret = xmlStrncat(ret, buf, 1);
1718
 
                ret = xmlStrcat(ret, node->name);
1719
 
                buf[0] = ';';
1720
 
                buf[1] = 0;
1721
 
                ret = xmlStrncat(ret, buf, 1);
1722
 
            }
1723
 
        }
1724
 
#if 0
1725
 
        else {
1726
 
            xmlGenericError(xmlGenericErrorContext,
1727
 
                            "xmlGetNodeListString : invalid node type %d\n",
1728
 
                            node->type);
1729
 
        }
1730
 
#endif
1731
 
        node = node->next;
1732
 
    }
1733
 
    return (ret);
1734
 
}
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(xmlDocPtr doc, xmlNodePtr list, int inLine)
1751
 
{
1752
 
    xmlNodePtr node = list;
1753
 
    xmlChar *ret = NULL;
1754
 
    xmlEntityPtr ent;
1755
 
 
1756
 
    if (list == NULL)
1757
 
        return (NULL);
1758
 
 
1759
 
    while (node != NULL) {
1760
 
        if ((node->type == XML_TEXT_NODE) ||
1761
 
            (node->type == XML_CDATA_SECTION_NODE)) {
1762
 
            if (inLine) {
1763
 
                ret = xmlStrcat(ret, node->content);
1764
 
            } else {
1765
 
                xmlChar *buffer;
1766
 
 
1767
 
                buffer = xmlEncodeSpecialChars(doc, node->content);
1768
 
                if (buffer != NULL) {
1769
 
                    ret = xmlStrcat(ret, buffer);
1770
 
                    xmlFree(buffer);
1771
 
                }
1772
 
            }
1773
 
        } else if (node->type == XML_ENTITY_REF_NODE) {
1774
 
            if (inLine) {
1775
 
                ent = xmlGetDocEntity(doc, node->name);
1776
 
                if (ent != NULL) {
1777
 
                    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
 
                    buffer =
1787
 
                        xmlNodeListGetRawString(doc, ent->children, 1);
1788
 
                    if (buffer != NULL) {
1789
 
                        ret = xmlStrcat(ret, buffer);
1790
 
                        xmlFree(buffer);
1791
 
                    }
1792
 
                } else {
1793
 
                    ret = xmlStrcat(ret, node->content);
1794
 
                }
1795
 
            } else {
1796
 
                xmlChar buf[2];
1797
 
 
1798
 
                buf[0] = '&';
1799
 
                buf[1] = 0;
1800
 
                ret = xmlStrncat(ret, buf, 1);
1801
 
                ret = xmlStrcat(ret, node->name);
1802
 
                buf[0] = ';';
1803
 
                buf[1] = 0;
1804
 
                ret = xmlStrncat(ret, buf, 1);
1805
 
            }
1806
 
        }
1807
 
#if 0
1808
 
        else {
1809
 
            xmlGenericError(xmlGenericErrorContext,
1810
 
                            "xmlGetNodeListString : invalid node type %d\n",
1811
 
                            node->type);
1812
 
        }
1813
 
#endif
1814
 
        node = node->next;
1815
 
    }
1816
 
    return (ret);
1817
 
}
1818
 
#endif /* LIBXML_TREE_ENABLED */
1819
 
 
1820
 
static xmlAttrPtr
1821
 
xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
1822
 
                   const xmlChar * name, const xmlChar * value,
1823
 
                   int eatname)
1824
 
{
1825
 
    xmlAttrPtr cur;
1826
 
    xmlDocPtr doc = NULL;
1827
 
 
1828
 
    if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) {
1829
 
        if ((eatname == 1) &&
1830
 
            ((node->doc == NULL) ||
1831
 
             (!(xmlDictOwns(node->doc->dict, name)))))
1832
 
            xmlFree((xmlChar *) name);
1833
 
        return (NULL);
1834
 
    }
1835
 
 
1836
 
    /*
1837
 
     * Allocate a new property and fill the fields.
1838
 
     */
1839
 
    cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1840
 
    if (cur == NULL) {
1841
 
        if ((eatname == 1) &&
1842
 
            ((node == NULL) || (node->doc == NULL) ||
1843
 
             (!(xmlDictOwns(node->doc->dict, name)))))
1844
 
            xmlFree((xmlChar *) name);
1845
 
        xmlTreeErrMemory("building attribute");
1846
 
        return (NULL);
1847
 
    }
1848
 
    memset(cur, 0, sizeof(xmlAttr));
1849
 
    cur->type = XML_ATTRIBUTE_NODE;
1850
 
 
1851
 
    cur->parent = node;
1852
 
    if (node != NULL) {
1853
 
        doc = node->doc;
1854
 
        cur->doc = doc;
1855
 
    }
1856
 
    cur->ns = ns;
1857
 
 
1858
 
    if (eatname == 0) {
1859
 
        if ((doc != NULL) && (doc->dict != NULL))
1860
 
            cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
1861
 
        else
1862
 
            cur->name = xmlStrdup(name);
1863
 
    } else
1864
 
        cur->name = name;
1865
 
 
1866
 
    if (value != NULL) {
1867
 
        xmlNodePtr tmp;
1868
 
 
1869
 
        if(!xmlCheckUTF8(value)) {
1870
 
            xmlTreeErr(XML_TREE_NOT_UTF8, (xmlNodePtr) doc,
1871
 
                       NULL);
1872
 
            if (doc != NULL)
1873
 
                doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
1874
 
        }
1875
 
        cur->children = xmlNewDocText(doc, value);
1876
 
        cur->last = NULL;
1877
 
        tmp = cur->children;
1878
 
        while (tmp != NULL) {
1879
 
            tmp->parent = (xmlNodePtr) cur;
1880
 
            if (tmp->next == NULL)
1881
 
                cur->last = tmp;
1882
 
            tmp = tmp->next;
1883
 
        }
1884
 
    }
1885
 
 
1886
 
    /*
1887
 
     * Add it at the end to preserve parsing order ...
1888
 
     */
1889
 
    if (node != NULL) {
1890
 
        if (node->properties == NULL) {
1891
 
            node->properties = cur;
1892
 
        } else {
1893
 
            xmlAttrPtr prev = node->properties;
1894
 
 
1895
 
            while (prev->next != NULL)
1896
 
                prev = prev->next;
1897
 
            prev->next = cur;
1898
 
            cur->prev = prev;
1899
 
        }
1900
 
    }
1901
 
 
1902
 
    if ((value != NULL) && (node != NULL) &&
1903
 
        (xmlIsID(node->doc, node, cur) == 1))
1904
 
        xmlAddID(NULL, node->doc, value, cur);
1905
 
 
1906
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1907
 
        xmlRegisterNodeDefaultValue((xmlNodePtr) cur);
1908
 
    return (cur);
1909
 
}
1910
 
 
1911
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
1912
 
    defined(LIBXML_SCHEMAS_ENABLED)
1913
 
/**
1914
 
 * xmlNewProp:
1915
 
 * @node:  the holding node
1916
 
 * @name:  the name of the attribute
1917
 
 * @value:  the value of the attribute
1918
 
 *
1919
 
 * Create a new property carried by a node.
1920
 
 * Returns a pointer to the attribute
1921
 
 */
1922
 
xmlAttrPtr
1923
 
xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
1924
 
 
1925
 
    if (name == NULL) {
1926
 
#ifdef DEBUG_TREE
1927
 
        xmlGenericError(xmlGenericErrorContext,
1928
 
                "xmlNewProp : name == NULL\n");
1929
 
#endif
1930
 
        return(NULL);
1931
 
    }
1932
 
 
1933
 
        return xmlNewPropInternal(node, NULL, name, value, 0);
1934
 
}
1935
 
#endif /* LIBXML_TREE_ENABLED */
1936
 
 
1937
 
/**
1938
 
 * xmlNewNsProp:
1939
 
 * @node:  the holding node
1940
 
 * @ns:  the namespace
1941
 
 * @name:  the name of the attribute
1942
 
 * @value:  the value of the attribute
1943
 
 *
1944
 
 * Create a new property tagged with a namespace and carried by a node.
1945
 
 * Returns a pointer to the attribute
1946
 
 */
1947
 
xmlAttrPtr
1948
 
xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
1949
 
           const xmlChar *value) {
1950
 
 
1951
 
    if (name == NULL) {
1952
 
#ifdef DEBUG_TREE
1953
 
        xmlGenericError(xmlGenericErrorContext,
1954
 
                "xmlNewNsProp : name == NULL\n");
1955
 
#endif
1956
 
        return(NULL);
1957
 
    }
1958
 
 
1959
 
    return xmlNewPropInternal(node, ns, name, value, 0);
1960
 
}
1961
 
 
1962
 
/**
1963
 
 * xmlNewNsPropEatName:
1964
 
 * @node:  the holding node
1965
 
 * @ns:  the namespace
1966
 
 * @name:  the name of the attribute
1967
 
 * @value:  the value of the attribute
1968
 
 *
1969
 
 * Create a new property tagged with a namespace and carried by a node.
1970
 
 * Returns a pointer to the attribute
1971
 
 */
1972
 
xmlAttrPtr
1973
 
xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name,
1974
 
           const xmlChar *value) {
1975
 
 
1976
 
    if (name == NULL) {
1977
 
#ifdef DEBUG_TREE
1978
 
        xmlGenericError(xmlGenericErrorContext,
1979
 
                "xmlNewNsPropEatName : name == NULL\n");
1980
 
#endif
1981
 
        return(NULL);
1982
 
    }
1983
 
 
1984
 
    return xmlNewPropInternal(node, ns, name, value, 1);
1985
 
}
1986
 
 
1987
 
/**
1988
 
 * xmlNewDocProp:
1989
 
 * @doc:  the document
1990
 
 * @name:  the name of the attribute
1991
 
 * @value:  the value of the attribute
1992
 
 *
1993
 
 * Create a new property carried by a document.
1994
 
 * Returns a pointer to the attribute
1995
 
 */
1996
 
xmlAttrPtr
1997
 
xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
1998
 
    xmlAttrPtr cur;
1999
 
 
2000
 
    if (name == NULL) {
2001
 
#ifdef DEBUG_TREE
2002
 
        xmlGenericError(xmlGenericErrorContext,
2003
 
                "xmlNewDocProp : name == NULL\n");
2004
 
#endif
2005
 
        return(NULL);
2006
 
    }
2007
 
 
2008
 
    /*
2009
 
     * Allocate a new property and fill the fields.
2010
 
     */
2011
 
    cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
2012
 
    if (cur == NULL) {
2013
 
        xmlTreeErrMemory("building attribute");
2014
 
        return(NULL);
2015
 
    }
2016
 
    memset(cur, 0, sizeof(xmlAttr));
2017
 
    cur->type = XML_ATTRIBUTE_NODE;
2018
 
 
2019
 
    if ((doc != NULL) && (doc->dict != NULL))
2020
 
        cur->name = xmlDictLookup(doc->dict, name, -1);
2021
 
    else
2022
 
        cur->name = xmlStrdup(name);
2023
 
    cur->doc = doc;
2024
 
    if (value != NULL) {
2025
 
        xmlNodePtr tmp;
2026
 
 
2027
 
        cur->children = xmlStringGetNodeList(doc, value);
2028
 
        cur->last = NULL;
2029
 
 
2030
 
        tmp = cur->children;
2031
 
        while (tmp != NULL) {
2032
 
            tmp->parent = (xmlNodePtr) cur;
2033
 
            if (tmp->next == NULL)
2034
 
                cur->last = tmp;
2035
 
            tmp = tmp->next;
2036
 
        }
2037
 
    }
2038
 
 
2039
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2040
 
        xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
2041
 
    return(cur);
2042
 
}
2043
 
 
2044
 
/**
2045
 
 * xmlFreePropList:
2046
 
 * @cur:  the first property in the list
2047
 
 *
2048
 
 * Free a property and all its siblings, all the children are freed too.
2049
 
 */
2050
 
void
2051
 
xmlFreePropList(xmlAttrPtr cur) {
2052
 
    xmlAttrPtr next;
2053
 
    if (cur == NULL) return;
2054
 
    while (cur != NULL) {
2055
 
        next = cur->next;
2056
 
        xmlFreeProp(cur);
2057
 
        cur = next;
2058
 
    }
2059
 
}
2060
 
 
2061
 
/**
2062
 
 * xmlFreeProp:
2063
 
 * @cur:  an attribute
2064
 
 *
2065
 
 * Free one attribute, all the content is freed too
2066
 
 */
2067
 
void
2068
 
xmlFreeProp(xmlAttrPtr cur) {
2069
 
    xmlDictPtr dict = NULL;
2070
 
    if (cur == NULL) return;
2071
 
 
2072
 
    if (cur->doc != NULL) dict = cur->doc->dict;
2073
 
 
2074
 
    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
2075
 
        xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
2076
 
 
2077
 
    /* Check for ID removal -> leading to invalid references ! */
2078
 
    if ((cur->doc != NULL) && (cur->atype == XML_ATTRIBUTE_ID)) {
2079
 
            xmlRemoveID(cur->doc, cur);
2080
 
    }
2081
 
    if (cur->children != NULL) xmlFreeNodeList(cur->children);
2082
 
    DICT_FREE(cur->name)
2083
 
    xmlFree(cur);
2084
 
}
2085
 
 
2086
 
/**
2087
 
 * xmlRemoveProp:
2088
 
 * @cur:  an attribute
2089
 
 *
2090
 
 * Unlink and free one attribute, all the content is freed too
2091
 
 * Note this doesn't work for namespace definition attributes
2092
 
 *
2093
 
 * Returns 0 if success and -1 in case of error.
2094
 
 */
2095
 
int
2096
 
xmlRemoveProp(xmlAttrPtr cur) {
2097
 
    xmlAttrPtr tmp;
2098
 
    if (cur == NULL) {
2099
 
#ifdef DEBUG_TREE
2100
 
        xmlGenericError(xmlGenericErrorContext,
2101
 
                "xmlRemoveProp : cur == NULL\n");
2102
 
#endif
2103
 
        return(-1);
2104
 
    }
2105
 
    if (cur->parent == NULL) {
2106
 
#ifdef DEBUG_TREE
2107
 
        xmlGenericError(xmlGenericErrorContext,
2108
 
                "xmlRemoveProp : cur->parent == NULL\n");
2109
 
#endif
2110
 
        return(-1);
2111
 
    }
2112
 
    tmp = cur->parent->properties;
2113
 
    if (tmp == cur) {
2114
 
        cur->parent->properties = cur->next;
2115
 
                if (cur->next != NULL)
2116
 
                        cur->next->prev = NULL;
2117
 
        xmlFreeProp(cur);
2118
 
        return(0);
2119
 
    }
2120
 
    while (tmp != NULL) {
2121
 
        if (tmp->next == cur) {
2122
 
            tmp->next = cur->next;
2123
 
            if (tmp->next != NULL)
2124
 
                tmp->next->prev = tmp;
2125
 
            xmlFreeProp(cur);
2126
 
            return(0);
2127
 
        }
2128
 
        tmp = tmp->next;
2129
 
    }
2130
 
#ifdef DEBUG_TREE
2131
 
    xmlGenericError(xmlGenericErrorContext,
2132
 
            "xmlRemoveProp : attribute not owned by its node\n");
2133
 
#endif
2134
 
    return(-1);
2135
 
}
2136
 
 
2137
 
/**
2138
 
 * xmlNewDocPI:
2139
 
 * @doc:  the target document
2140
 
 * @name:  the processing instruction name
2141
 
 * @content:  the PI content
2142
 
 *
2143
 
 * Creation of a processing instruction element.
2144
 
 * Returns a pointer to the new node object.
2145
 
 */
2146
 
xmlNodePtr
2147
 
xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) {
2148
 
    xmlNodePtr cur;
2149
 
 
2150
 
    if (name == NULL) {
2151
 
#ifdef DEBUG_TREE
2152
 
        xmlGenericError(xmlGenericErrorContext,
2153
 
                "xmlNewPI : name == NULL\n");
2154
 
#endif
2155
 
        return(NULL);
2156
 
    }
2157
 
 
2158
 
    /*
2159
 
     * Allocate a new node and fill the fields.
2160
 
     */
2161
 
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2162
 
    if (cur == NULL) {
2163
 
        xmlTreeErrMemory("building PI");
2164
 
        return(NULL);
2165
 
    }
2166
 
    memset(cur, 0, sizeof(xmlNode));
2167
 
    cur->type = XML_PI_NODE;
2168
 
 
2169
 
    if ((doc != NULL) && (doc->dict != NULL))
2170
 
        cur->name = xmlDictLookup(doc->dict, name, -1);
2171
 
    else
2172
 
        cur->name = xmlStrdup(name);
2173
 
    if (content != NULL) {
2174
 
        cur->content = xmlStrdup(content);
2175
 
    }
2176
 
    cur->doc = doc;
2177
 
 
2178
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2179
 
        xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
2180
 
    return(cur);
2181
 
}
2182
 
 
2183
 
/**
2184
 
 * xmlNewPI:
2185
 
 * @name:  the processing instruction name
2186
 
 * @content:  the PI content
2187
 
 *
2188
 
 * Creation of a processing instruction element.
2189
 
 * Use xmlDocNewPI preferably to get string interning
2190
 
 *
2191
 
 * Returns a pointer to the new node object.
2192
 
 */
2193
 
xmlNodePtr
2194
 
xmlNewPI(const xmlChar *name, const xmlChar *content) {
2195
 
    return(xmlNewDocPI(NULL, name, content));
2196
 
}
2197
 
 
2198
 
/**
2199
 
 * xmlNewNode:
2200
 
 * @ns:  namespace if any
2201
 
 * @name:  the node name
2202
 
 *
2203
 
 * Creation of a new node element. @ns is optional (NULL).
2204
 
 *
2205
 
 * Returns a pointer to the new node object. Uses xmlStrdup() to make
2206
 
 * copy of @name.
2207
 
 */
2208
 
xmlNodePtr
2209
 
xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
2210
 
    xmlNodePtr cur;
2211
 
 
2212
 
    if (name == NULL) {
2213
 
#ifdef DEBUG_TREE
2214
 
        xmlGenericError(xmlGenericErrorContext,
2215
 
                "xmlNewNode : name == NULL\n");
2216
 
#endif
2217
 
        return(NULL);
2218
 
    }
2219
 
 
2220
 
    /*
2221
 
     * Allocate a new node and fill the fields.
2222
 
     */
2223
 
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2224
 
    if (cur == NULL) {
2225
 
        xmlTreeErrMemory("building node");
2226
 
        return(NULL);
2227
 
    }
2228
 
    memset(cur, 0, sizeof(xmlNode));
2229
 
    cur->type = XML_ELEMENT_NODE;
2230
 
 
2231
 
    cur->name = xmlStrdup(name);
2232
 
    cur->ns = ns;
2233
 
 
2234
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2235
 
        xmlRegisterNodeDefaultValue(cur);
2236
 
    return(cur);
2237
 
}
2238
 
 
2239
 
/**
2240
 
 * xmlNewNodeEatName:
2241
 
 * @ns:  namespace if any
2242
 
 * @name:  the node name
2243
 
 *
2244
 
 * Creation of a new node element. @ns is optional (NULL).
2245
 
 *
2246
 
 * Returns a pointer to the new node object, with pointer @name as
2247
 
 * new node's name. Use xmlNewNode() if a copy of @name string is
2248
 
 * is needed as new node's name.
2249
 
 */
2250
 
xmlNodePtr
2251
 
xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) {
2252
 
    xmlNodePtr cur;
2253
 
 
2254
 
    if (name == NULL) {
2255
 
#ifdef DEBUG_TREE
2256
 
        xmlGenericError(xmlGenericErrorContext,
2257
 
                "xmlNewNode : name == NULL\n");
2258
 
#endif
2259
 
        return(NULL);
2260
 
    }
2261
 
 
2262
 
    /*
2263
 
     * Allocate a new node and fill the fields.
2264
 
     */
2265
 
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2266
 
    if (cur == NULL) {
2267
 
        xmlTreeErrMemory("building node");
2268
 
        /* we can't check here that name comes from the doc dictionnary */
2269
 
        return(NULL);
2270
 
    }
2271
 
    memset(cur, 0, sizeof(xmlNode));
2272
 
    cur->type = XML_ELEMENT_NODE;
2273
 
 
2274
 
    cur->name = name;
2275
 
    cur->ns = ns;
2276
 
 
2277
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2278
 
        xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
2279
 
    return(cur);
2280
 
}
2281
 
 
2282
 
/**
2283
 
 * xmlNewDocNode:
2284
 
 * @doc:  the document
2285
 
 * @ns:  namespace if any
2286
 
 * @name:  the node name
2287
 
 * @content:  the XML text content if any
2288
 
 *
2289
 
 * Creation of a new node element within a document. @ns and @content
2290
 
 * are optional (NULL).
2291
 
 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2292
 
 *       references, but XML special chars need to be escaped first by using
2293
 
 *       xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2294
 
 *       need entities support.
2295
 
 *
2296
 
 * Returns a pointer to the new node object.
2297
 
 */
2298
 
xmlNodePtr
2299
 
xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
2300
 
              const xmlChar *name, const xmlChar *content) {
2301
 
    xmlNodePtr cur;
2302
 
 
2303
 
    if ((doc != NULL) && (doc->dict != NULL))
2304
 
        cur = xmlNewNodeEatName(ns, (xmlChar *)
2305
 
                                xmlDictLookup(doc->dict, name, -1));
2306
 
    else
2307
 
        cur = xmlNewNode(ns, name);
2308
 
    if (cur != NULL) {
2309
 
        cur->doc = doc;
2310
 
        if (content != NULL) {
2311
 
            cur->children = xmlStringGetNodeList(doc, content);
2312
 
            UPDATE_LAST_CHILD_AND_PARENT(cur)
2313
 
        }
2314
 
    }
2315
 
 
2316
 
    return(cur);
2317
 
}
2318
 
 
2319
 
/**
2320
 
 * xmlNewDocNodeEatName:
2321
 
 * @doc:  the document
2322
 
 * @ns:  namespace if any
2323
 
 * @name:  the node name
2324
 
 * @content:  the XML text content if any
2325
 
 *
2326
 
 * Creation of a new node element within a document. @ns and @content
2327
 
 * are optional (NULL).
2328
 
 * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
2329
 
 *       references, but XML special chars need to be escaped first by using
2330
 
 *       xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
2331
 
 *       need entities support.
2332
 
 *
2333
 
 * Returns a pointer to the new node object.
2334
 
 */
2335
 
xmlNodePtr
2336
 
xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns,
2337
 
              xmlChar *name, const xmlChar *content) {
2338
 
    xmlNodePtr cur;
2339
 
 
2340
 
    cur = xmlNewNodeEatName(ns, name);
2341
 
    if (cur != NULL) {
2342
 
        cur->doc = doc;
2343
 
        if (content != NULL) {
2344
 
            cur->children = xmlStringGetNodeList(doc, content);
2345
 
            UPDATE_LAST_CHILD_AND_PARENT(cur)
2346
 
        }
2347
 
    } else {
2348
 
        /* if name don't come from the doc dictionnary free it here */
2349
 
        if ((name != NULL) && (doc != NULL) &&
2350
 
            (!(xmlDictOwns(doc->dict, name))))
2351
 
            xmlFree(name);
2352
 
    }
2353
 
    return(cur);
2354
 
}
2355
 
 
2356
 
#ifdef LIBXML_TREE_ENABLED
2357
 
/**
2358
 
 * xmlNewDocRawNode:
2359
 
 * @doc:  the document
2360
 
 * @ns:  namespace if any
2361
 
 * @name:  the node name
2362
 
 * @content:  the text content if any
2363
 
 *
2364
 
 * Creation of a new node element within a document. @ns and @content
2365
 
 * are optional (NULL).
2366
 
 *
2367
 
 * Returns a pointer to the new node object.
2368
 
 */
2369
 
xmlNodePtr
2370
 
xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
2371
 
                 const xmlChar *name, const xmlChar *content) {
2372
 
    xmlNodePtr cur;
2373
 
 
2374
 
    cur = xmlNewDocNode(doc, ns, name, NULL);
2375
 
    if (cur != NULL) {
2376
 
        cur->doc = doc;
2377
 
        if (content != NULL) {
2378
 
            cur->children = xmlNewDocText(doc, content);
2379
 
            UPDATE_LAST_CHILD_AND_PARENT(cur)
2380
 
        }
2381
 
    }
2382
 
    return(cur);
2383
 
}
2384
 
 
2385
 
/**
2386
 
 * xmlNewDocFragment:
2387
 
 * @doc:  the document owning the fragment
2388
 
 *
2389
 
 * Creation of a new Fragment node.
2390
 
 * Returns a pointer to the new node object.
2391
 
 */
2392
 
xmlNodePtr
2393
 
xmlNewDocFragment(xmlDocPtr doc) {
2394
 
    xmlNodePtr cur;
2395
 
 
2396
 
    /*
2397
 
     * Allocate a new DocumentFragment node and fill the fields.
2398
 
     */
2399
 
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2400
 
    if (cur == NULL) {
2401
 
        xmlTreeErrMemory("building fragment");
2402
 
        return(NULL);
2403
 
    }
2404
 
    memset(cur, 0, sizeof(xmlNode));
2405
 
    cur->type = XML_DOCUMENT_FRAG_NODE;
2406
 
 
2407
 
    cur->doc = doc;
2408
 
 
2409
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2410
 
        xmlRegisterNodeDefaultValue(cur);
2411
 
    return(cur);
2412
 
}
2413
 
#endif /* LIBXML_TREE_ENABLED */
2414
 
 
2415
 
/**
2416
 
 * xmlNewText:
2417
 
 * @content:  the text content
2418
 
 *
2419
 
 * Creation of a new text node.
2420
 
 * Returns a pointer to the new node object.
2421
 
 */
2422
 
xmlNodePtr
2423
 
xmlNewText(const xmlChar *content) {
2424
 
    xmlNodePtr cur;
2425
 
 
2426
 
    /*
2427
 
     * Allocate a new node and fill the fields.
2428
 
     */
2429
 
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2430
 
    if (cur == NULL) {
2431
 
        xmlTreeErrMemory("building text");
2432
 
        return(NULL);
2433
 
    }
2434
 
    memset(cur, 0, sizeof(xmlNode));
2435
 
    cur->type = XML_TEXT_NODE;
2436
 
 
2437
 
    cur->name = xmlStringText;
2438
 
    if (content != NULL) {
2439
 
        cur->content = xmlStrdup(content);
2440
 
    }
2441
 
 
2442
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2443
 
        xmlRegisterNodeDefaultValue(cur);
2444
 
    return(cur);
2445
 
}
2446
 
 
2447
 
#ifdef LIBXML_TREE_ENABLED
2448
 
/**
2449
 
 * xmlNewTextChild:
2450
 
 * @parent:  the parent node
2451
 
 * @ns:  a namespace if any
2452
 
 * @name:  the name of the child
2453
 
 * @content:  the text content of the child if any.
2454
 
 *
2455
 
 * Creation of a new child element, added at the end of @parent children list.
2456
 
 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2457
 
 * created element inherits the namespace of @parent. If @content is non NULL,
2458
 
 * a child TEXT node will be created containing the string @content.
2459
 
 * NOTE: Use xmlNewChild() if @content will contain entities that need to be
2460
 
 * preserved. Use this function, xmlNewTextChild(), if you need to ensure that
2461
 
 * reserved XML chars that might appear in @content, such as the ampersand,
2462
 
 * greater-than or less-than signs, are automatically replaced by their XML
2463
 
 * escaped entity representations.
2464
 
 *
2465
 
 * Returns a pointer to the new node object.
2466
 
 */
2467
 
xmlNodePtr
2468
 
xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
2469
 
            const xmlChar *name, const xmlChar *content) {
2470
 
    xmlNodePtr cur, prev;
2471
 
 
2472
 
    if (parent == NULL) {
2473
 
#ifdef DEBUG_TREE
2474
 
        xmlGenericError(xmlGenericErrorContext,
2475
 
                "xmlNewTextChild : parent == NULL\n");
2476
 
#endif
2477
 
        return(NULL);
2478
 
    }
2479
 
 
2480
 
    if (name == NULL) {
2481
 
#ifdef DEBUG_TREE
2482
 
        xmlGenericError(xmlGenericErrorContext,
2483
 
                "xmlNewTextChild : name == NULL\n");
2484
 
#endif
2485
 
        return(NULL);
2486
 
    }
2487
 
 
2488
 
    /*
2489
 
     * Allocate a new node
2490
 
     */
2491
 
    if (parent->type == XML_ELEMENT_NODE) {
2492
 
        if (ns == NULL)
2493
 
            cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
2494
 
        else
2495
 
            cur = xmlNewDocRawNode(parent->doc, ns, name, content);
2496
 
    } else if ((parent->type == XML_DOCUMENT_NODE) ||
2497
 
               (parent->type == XML_HTML_DOCUMENT_NODE)) {
2498
 
        if (ns == NULL)
2499
 
            cur = xmlNewDocRawNode((xmlDocPtr) parent, NULL, name, content);
2500
 
        else
2501
 
            cur = xmlNewDocRawNode((xmlDocPtr) parent, ns, name, content);
2502
 
    } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
2503
 
            cur = xmlNewDocRawNode( parent->doc, ns, name, content);
2504
 
    } else {
2505
 
        return(NULL);
2506
 
    }
2507
 
    if (cur == NULL) return(NULL);
2508
 
 
2509
 
    /*
2510
 
     * add the new element at the end of the children list.
2511
 
     */
2512
 
    cur->type = XML_ELEMENT_NODE;
2513
 
    cur->parent = parent;
2514
 
    cur->doc = parent->doc;
2515
 
    if (parent->children == NULL) {
2516
 
        parent->children = cur;
2517
 
        parent->last = cur;
2518
 
    } else {
2519
 
        prev = parent->last;
2520
 
        prev->next = cur;
2521
 
        cur->prev = prev;
2522
 
        parent->last = cur;
2523
 
    }
2524
 
 
2525
 
    return(cur);
2526
 
}
2527
 
#endif /* LIBXML_TREE_ENABLED */
2528
 
 
2529
 
/**
2530
 
 * xmlNewCharRef:
2531
 
 * @doc: the document
2532
 
 * @name:  the char ref string, starting with # or "&# ... ;"
2533
 
 *
2534
 
 * Creation of a new character reference node.
2535
 
 * Returns a pointer to the new node object.
2536
 
 */
2537
 
xmlNodePtr
2538
 
xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
2539
 
    xmlNodePtr cur;
2540
 
 
2541
 
    if (name == NULL)
2542
 
        return(NULL);
2543
 
 
2544
 
    /*
2545
 
     * Allocate a new node and fill the fields.
2546
 
     */
2547
 
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2548
 
    if (cur == NULL) {
2549
 
        xmlTreeErrMemory("building character reference");
2550
 
        return(NULL);
2551
 
    }
2552
 
    memset(cur, 0, sizeof(xmlNode));
2553
 
    cur->type = XML_ENTITY_REF_NODE;
2554
 
 
2555
 
    cur->doc = doc;
2556
 
    if (name[0] == '&') {
2557
 
        int len;
2558
 
        name++;
2559
 
        len = xmlStrlen(name);
2560
 
        if (name[len - 1] == ';')
2561
 
            cur->name = xmlStrndup(name, len - 1);
2562
 
        else
2563
 
            cur->name = xmlStrndup(name, len);
2564
 
    } else
2565
 
        cur->name = xmlStrdup(name);
2566
 
 
2567
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2568
 
        xmlRegisterNodeDefaultValue(cur);
2569
 
    return(cur);
2570
 
}
2571
 
 
2572
 
/**
2573
 
 * xmlNewReference:
2574
 
 * @doc: the document
2575
 
 * @name:  the reference name, or the reference string with & and ;
2576
 
 *
2577
 
 * Creation of a new reference node.
2578
 
 * Returns a pointer to the new node object.
2579
 
 */
2580
 
xmlNodePtr
2581
 
xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
2582
 
    xmlNodePtr cur;
2583
 
    xmlEntityPtr ent;
2584
 
 
2585
 
    if (name == NULL)
2586
 
        return(NULL);
2587
 
 
2588
 
    /*
2589
 
     * Allocate a new node and fill the fields.
2590
 
     */
2591
 
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2592
 
    if (cur == NULL) {
2593
 
        xmlTreeErrMemory("building reference");
2594
 
        return(NULL);
2595
 
    }
2596
 
    memset(cur, 0, sizeof(xmlNode));
2597
 
    cur->type = XML_ENTITY_REF_NODE;
2598
 
 
2599
 
    cur->doc = doc;
2600
 
    if (name[0] == '&') {
2601
 
        int len;
2602
 
        name++;
2603
 
        len = xmlStrlen(name);
2604
 
        if (name[len - 1] == ';')
2605
 
            cur->name = xmlStrndup(name, len - 1);
2606
 
        else
2607
 
            cur->name = xmlStrndup(name, len);
2608
 
    } else
2609
 
        cur->name = xmlStrdup(name);
2610
 
 
2611
 
    ent = xmlGetDocEntity(doc, cur->name);
2612
 
    if (ent != NULL) {
2613
 
        cur->content = ent->content;
2614
 
        /*
2615
 
         * The parent pointer in entity is a DTD pointer and thus is NOT
2616
 
         * updated.  Not sure if this is 100% correct.
2617
 
         *  -George
2618
 
         */
2619
 
        cur->children = (xmlNodePtr) ent;
2620
 
        cur->last = (xmlNodePtr) ent;
2621
 
    }
2622
 
 
2623
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2624
 
        xmlRegisterNodeDefaultValue(cur);
2625
 
    return(cur);
2626
 
}
2627
 
 
2628
 
/**
2629
 
 * xmlNewDocText:
2630
 
 * @doc: the document
2631
 
 * @content:  the text content
2632
 
 *
2633
 
 * Creation of a new text node within a document.
2634
 
 * Returns a pointer to the new node object.
2635
 
 */
2636
 
xmlNodePtr
2637
 
xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
2638
 
    xmlNodePtr cur;
2639
 
 
2640
 
    cur = xmlNewText(content);
2641
 
    if (cur != NULL) cur->doc = doc;
2642
 
    return(cur);
2643
 
}
2644
 
 
2645
 
/**
2646
 
 * xmlNewTextLen:
2647
 
 * @content:  the text content
2648
 
 * @len:  the text len.
2649
 
 *
2650
 
 * Creation of a new text node with an extra parameter for the content's length
2651
 
 * Returns a pointer to the new node object.
2652
 
 */
2653
 
xmlNodePtr
2654
 
xmlNewTextLen(const xmlChar *content, int len) {
2655
 
    xmlNodePtr cur;
2656
 
 
2657
 
    /*
2658
 
     * Allocate a new node and fill the fields.
2659
 
     */
2660
 
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2661
 
    if (cur == NULL) {
2662
 
        xmlTreeErrMemory("building text");
2663
 
        return(NULL);
2664
 
    }
2665
 
    memset(cur, 0, sizeof(xmlNode));
2666
 
    cur->type = XML_TEXT_NODE;
2667
 
 
2668
 
    cur->name = xmlStringText;
2669
 
    if (content != NULL) {
2670
 
        cur->content = xmlStrndup(content, len);
2671
 
    }
2672
 
 
2673
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2674
 
        xmlRegisterNodeDefaultValue(cur);
2675
 
    return(cur);
2676
 
}
2677
 
 
2678
 
/**
2679
 
 * xmlNewDocTextLen:
2680
 
 * @doc: the document
2681
 
 * @content:  the text content
2682
 
 * @len:  the text len.
2683
 
 *
2684
 
 * Creation of a new text node with an extra content length parameter. The
2685
 
 * text node pertain to a given document.
2686
 
 * Returns a pointer to the new node object.
2687
 
 */
2688
 
xmlNodePtr
2689
 
xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
2690
 
    xmlNodePtr cur;
2691
 
 
2692
 
    cur = xmlNewTextLen(content, len);
2693
 
    if (cur != NULL) cur->doc = doc;
2694
 
    return(cur);
2695
 
}
2696
 
 
2697
 
/**
2698
 
 * xmlNewComment:
2699
 
 * @content:  the comment content
2700
 
 *
2701
 
 * Creation of a new node containing a comment.
2702
 
 * Returns a pointer to the new node object.
2703
 
 */
2704
 
xmlNodePtr
2705
 
xmlNewComment(const xmlChar *content) {
2706
 
    xmlNodePtr cur;
2707
 
 
2708
 
    /*
2709
 
     * Allocate a new node and fill the fields.
2710
 
     */
2711
 
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2712
 
    if (cur == NULL) {
2713
 
        xmlTreeErrMemory("building comment");
2714
 
        return(NULL);
2715
 
    }
2716
 
    memset(cur, 0, sizeof(xmlNode));
2717
 
    cur->type = XML_COMMENT_NODE;
2718
 
 
2719
 
    cur->name = xmlStringComment;
2720
 
    if (content != NULL) {
2721
 
        cur->content = xmlStrdup(content);
2722
 
    }
2723
 
 
2724
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2725
 
        xmlRegisterNodeDefaultValue(cur);
2726
 
    return(cur);
2727
 
}
2728
 
 
2729
 
/**
2730
 
 * xmlNewCDataBlock:
2731
 
 * @doc:  the document
2732
 
 * @content:  the CDATA block content content
2733
 
 * @len:  the length of the block
2734
 
 *
2735
 
 * Creation of a new node containing a CDATA block.
2736
 
 * Returns a pointer to the new node object.
2737
 
 */
2738
 
xmlNodePtr
2739
 
xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
2740
 
    xmlNodePtr cur;
2741
 
 
2742
 
    /*
2743
 
     * Allocate a new node and fill the fields.
2744
 
     */
2745
 
    cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
2746
 
    if (cur == NULL) {
2747
 
        xmlTreeErrMemory("building CDATA");
2748
 
        return(NULL);
2749
 
    }
2750
 
    memset(cur, 0, sizeof(xmlNode));
2751
 
    cur->type = XML_CDATA_SECTION_NODE;
2752
 
    cur->doc = doc;
2753
 
 
2754
 
    if (content != NULL) {
2755
 
        cur->content = xmlStrndup(content, len);
2756
 
    }
2757
 
 
2758
 
    if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2759
 
        xmlRegisterNodeDefaultValue(cur);
2760
 
    return(cur);
2761
 
}
2762
 
 
2763
 
/**
2764
 
 * xmlNewDocComment:
2765
 
 * @doc:  the document
2766
 
 * @content:  the comment content
2767
 
 *
2768
 
 * Creation of a new node containing a comment within a document.
2769
 
 * Returns a pointer to the new node object.
2770
 
 */
2771
 
xmlNodePtr
2772
 
xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
2773
 
    xmlNodePtr cur;
2774
 
 
2775
 
    cur = xmlNewComment(content);
2776
 
    if (cur != NULL) cur->doc = doc;
2777
 
    return(cur);
2778
 
}
2779
 
 
2780
 
/**
2781
 
 * xmlSetTreeDoc:
2782
 
 * @tree:  the top element
2783
 
 * @doc:  the document
2784
 
 *
2785
 
 * update all nodes under the tree to point to the right document
2786
 
 */
2787
 
void
2788
 
xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) {
2789
 
    xmlAttrPtr prop;
2790
 
 
2791
 
    if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL))
2792
 
        return;
2793
 
    if (tree->doc != doc) {
2794
 
        if(tree->type == XML_ELEMENT_NODE) {
2795
 
            prop = tree->properties;
2796
 
            while (prop != NULL) {
2797
 
                prop->doc = doc;
2798
 
                xmlSetListDoc(prop->children, doc);
2799
 
                prop = prop->next;
2800
 
            }
2801
 
        }
2802
 
        if (tree->children != NULL)
2803
 
            xmlSetListDoc(tree->children, doc);
2804
 
        tree->doc = doc;
2805
 
    }
2806
 
}
2807
 
 
2808
 
/**
2809
 
 * xmlSetListDoc:
2810
 
 * @list:  the first element
2811
 
 * @doc:  the document
2812
 
 *
2813
 
 * update all nodes in the list to point to the right document
2814
 
 */
2815
 
void
2816
 
xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc) {
2817
 
    xmlNodePtr cur;
2818
 
 
2819
 
    if ((list == NULL) || (list->type == XML_NAMESPACE_DECL))
2820
 
        return;
2821
 
    cur = list;
2822
 
    while (cur != NULL) {
2823
 
        if (cur->doc != doc)
2824
 
            xmlSetTreeDoc(cur, doc);
2825
 
        cur = cur->next;
2826
 
    }
2827
 
}
2828
 
 
2829
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2830
 
/**
2831
 
 * xmlNewChild:
2832
 
 * @parent:  the parent node
2833
 
 * @ns:  a namespace if any
2834
 
 * @name:  the name of the child
2835
 
 * @content:  the XML content of the child if any.
2836
 
 *
2837
 
 * Creation of a new child element, added at the end of @parent children list.
2838
 
 * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly
2839
 
 * created element inherits the namespace of @parent. If @content is non NULL,
2840
 
 * a child list containing the TEXTs and ENTITY_REFs node will be created.
2841
 
 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
2842
 
 *       references. XML special chars must be escaped first by using
2843
 
 *       xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used.
2844
 
 *
2845
 
 * Returns a pointer to the new node object.
2846
 
 */
2847
 
xmlNodePtr
2848
 
xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
2849
 
            const xmlChar *name, const xmlChar *content) {
2850
 
    xmlNodePtr cur, prev;
2851
 
 
2852
 
    if (parent == NULL) {
2853
 
#ifdef DEBUG_TREE
2854
 
        xmlGenericError(xmlGenericErrorContext,
2855
 
                "xmlNewChild : parent == NULL\n");
2856
 
#endif
2857
 
        return(NULL);
2858
 
    }
2859
 
 
2860
 
    if (name == NULL) {
2861
 
#ifdef DEBUG_TREE
2862
 
        xmlGenericError(xmlGenericErrorContext,
2863
 
                "xmlNewChild : name == NULL\n");
2864
 
#endif
2865
 
        return(NULL);
2866
 
    }
2867
 
 
2868
 
    /*
2869
 
     * Allocate a new node
2870
 
     */
2871
 
    if (parent->type == XML_ELEMENT_NODE) {
2872
 
        if (ns == NULL)
2873
 
            cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
2874
 
        else
2875
 
            cur = xmlNewDocNode(parent->doc, ns, name, content);
2876
 
    } else if ((parent->type == XML_DOCUMENT_NODE) ||
2877
 
               (parent->type == XML_HTML_DOCUMENT_NODE)) {
2878
 
        if (ns == NULL)
2879
 
            cur = xmlNewDocNode((xmlDocPtr) parent, NULL, name, content);
2880
 
        else
2881
 
            cur = xmlNewDocNode((xmlDocPtr) parent, ns, name, content);
2882
 
    } else if (parent->type == XML_DOCUMENT_FRAG_NODE) {
2883
 
            cur = xmlNewDocNode( parent->doc, ns, name, content);
2884
 
    } else {
2885
 
        return(NULL);
2886
 
    }
2887
 
    if (cur == NULL) return(NULL);
2888
 
 
2889
 
    /*
2890
 
     * add the new element at the end of the children list.
2891
 
     */
2892
 
    cur->type = XML_ELEMENT_NODE;
2893
 
    cur->parent = parent;
2894
 
    cur->doc = parent->doc;
2895
 
    if (parent->children == NULL) {
2896
 
        parent->children = cur;
2897
 
        parent->last = cur;
2898
 
    } else {
2899
 
        prev = parent->last;
2900
 
        prev->next = cur;
2901
 
        cur->prev = prev;
2902
 
        parent->last = cur;
2903
 
    }
2904
 
 
2905
 
    return(cur);
2906
 
}
2907
 
#endif /* LIBXML_TREE_ENABLED */
2908
 
 
2909
 
/**
2910
 
 * xmlAddPropSibling:
2911
 
 * @prev:  the attribute to which @prop is added after
2912
 
 * @cur:   the base attribute passed to calling function
2913
 
 * @prop:  the new attribute
2914
 
 *
2915
 
 * Add a new attribute after @prev using @cur as base attribute.
2916
 
 * When inserting before @cur, @prev is passed as @cur->prev.
2917
 
 * When inserting after @cur, @prev is passed as @cur.
2918
 
 * If an existing attribute is found it is detroyed prior to adding @prop.
2919
 
 *
2920
 
 * Returns the attribute being inserted or NULL in case of error.
2921
 
 */
2922
 
static xmlNodePtr
2923
 
xmlAddPropSibling(xmlNodePtr prev, xmlNodePtr cur, xmlNodePtr prop) {
2924
 
        xmlAttrPtr attr;
2925
 
 
2926
 
        if ((cur == NULL) || (cur->type != XML_ATTRIBUTE_NODE) ||
2927
 
            (prop == NULL) || (prop->type != XML_ATTRIBUTE_NODE) ||
2928
 
            ((prev != NULL) && (prev->type != XML_ATTRIBUTE_NODE)))
2929
 
                return(NULL);
2930
 
 
2931
 
        /* check if an attribute with the same name exists */
2932
 
        if (prop->ns == NULL)
2933
 
                attr = xmlHasNsProp(cur->parent, prop->name, NULL);
2934
 
        else
2935
 
                attr = xmlHasNsProp(cur->parent, prop->name, prop->ns->href);
2936
 
 
2937
 
        if (prop->doc != cur->doc) {
2938
 
                xmlSetTreeDoc(prop, cur->doc);
2939
 
        }
2940
 
        prop->parent = cur->parent;
2941
 
        prop->prev = prev;
2942
 
        if (prev != NULL) {
2943
 
                prop->next = prev->next;
2944
 
                prev->next = prop;
2945
 
                if (prop->next)
2946
 
                        prop->next->prev = prop;
2947
 
        } else {
2948
 
                prop->next = cur;
2949
 
                cur->prev = prop;
2950
 
        }
2951
 
        if (prop->prev == NULL && prop->parent != NULL)
2952
 
                prop->parent->properties = (xmlAttrPtr) prop;
2953
 
        if ((attr != NULL) && (attr->type != XML_ATTRIBUTE_DECL)) {
2954
 
                /* different instance, destroy it (attributes must be unique) */
2955
 
                xmlRemoveProp((xmlAttrPtr) attr);
2956
 
        }
2957
 
        return prop;
2958
 
}
2959
 
 
2960
 
/**
2961
 
 * xmlAddNextSibling:
2962
 
 * @cur:  the child node
2963
 
 * @elem:  the new node
2964
 
 *
2965
 
 * Add a new node @elem as the next sibling of @cur
2966
 
 * If the new node was already inserted in a document it is
2967
 
 * first unlinked from its existing context.
2968
 
 * As a result of text merging @elem may be freed.
2969
 
 * If the new node is ATTRIBUTE, it is added into properties instead of children.
2970
 
 * If there is an attribute with equal name, it is first destroyed.
2971
 
 *
2972
 
 * Returns the new node or NULL in case of error.
2973
 
 */
2974
 
xmlNodePtr
2975
 
xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
2976
 
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
2977
 
#ifdef DEBUG_TREE
2978
 
        xmlGenericError(xmlGenericErrorContext,
2979
 
                "xmlAddNextSibling : cur == NULL\n");
2980
 
#endif
2981
 
        return(NULL);
2982
 
    }
2983
 
    if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
2984
 
#ifdef DEBUG_TREE
2985
 
        xmlGenericError(xmlGenericErrorContext,
2986
 
                "xmlAddNextSibling : elem == NULL\n");
2987
 
#endif
2988
 
        return(NULL);
2989
 
    }
2990
 
 
2991
 
    if (cur == elem) {
2992
 
#ifdef DEBUG_TREE
2993
 
        xmlGenericError(xmlGenericErrorContext,
2994
 
                "xmlAddNextSibling : cur == elem\n");
2995
 
#endif
2996
 
        return(NULL);
2997
 
    }
2998
 
 
2999
 
    xmlUnlinkNode(elem);
3000
 
 
3001
 
    if (elem->type == XML_TEXT_NODE) {
3002
 
        if (cur->type == XML_TEXT_NODE) {
3003
 
            xmlNodeAddContent(cur, elem->content);
3004
 
            xmlFreeNode(elem);
3005
 
            return(cur);
3006
 
        }
3007
 
        if ((cur->next != NULL) && (cur->next->type == XML_TEXT_NODE) &&
3008
 
            (cur->name == cur->next->name)) {
3009
 
            xmlChar *tmp;
3010
 
 
3011
 
            tmp = xmlStrdup(elem->content);
3012
 
            tmp = xmlStrcat(tmp, cur->next->content);
3013
 
            xmlNodeSetContent(cur->next, tmp);
3014
 
            xmlFree(tmp);
3015
 
            xmlFreeNode(elem);
3016
 
            return(cur->next);
3017
 
        }
3018
 
    } else if (elem->type == XML_ATTRIBUTE_NODE) {
3019
 
                return xmlAddPropSibling(cur, cur, elem);
3020
 
    }
3021
 
 
3022
 
    if (elem->doc != cur->doc) {
3023
 
        xmlSetTreeDoc(elem, cur->doc);
3024
 
    }
3025
 
    elem->parent = cur->parent;
3026
 
    elem->prev = cur;
3027
 
    elem->next = cur->next;
3028
 
    cur->next = elem;
3029
 
    if (elem->next != NULL)
3030
 
        elem->next->prev = elem;
3031
 
    if ((elem->parent != NULL) && (elem->parent->last == cur))
3032
 
        elem->parent->last = elem;
3033
 
    return(elem);
3034
 
}
3035
 
 
3036
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
3037
 
    defined(LIBXML_SCHEMAS_ENABLED)
3038
 
/**
3039
 
 * xmlAddPrevSibling:
3040
 
 * @cur:  the child node
3041
 
 * @elem:  the new node
3042
 
 *
3043
 
 * Add a new node @elem as the previous sibling of @cur
3044
 
 * merging adjacent TEXT nodes (@elem may be freed)
3045
 
 * If the new node was already inserted in a document it is
3046
 
 * first unlinked from its existing context.
3047
 
 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3048
 
 * If there is an attribute with equal name, it is first destroyed.
3049
 
 *
3050
 
 * Returns the new node or NULL in case of error.
3051
 
 */
3052
 
xmlNodePtr
3053
 
xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
3054
 
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3055
 
#ifdef DEBUG_TREE
3056
 
        xmlGenericError(xmlGenericErrorContext,
3057
 
                "xmlAddPrevSibling : cur == NULL\n");
3058
 
#endif
3059
 
        return(NULL);
3060
 
    }
3061
 
    if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
3062
 
#ifdef DEBUG_TREE
3063
 
        xmlGenericError(xmlGenericErrorContext,
3064
 
                "xmlAddPrevSibling : elem == NULL\n");
3065
 
#endif
3066
 
        return(NULL);
3067
 
    }
3068
 
 
3069
 
    if (cur == elem) {
3070
 
#ifdef DEBUG_TREE
3071
 
        xmlGenericError(xmlGenericErrorContext,
3072
 
                "xmlAddPrevSibling : cur == elem\n");
3073
 
#endif
3074
 
        return(NULL);
3075
 
    }
3076
 
 
3077
 
    xmlUnlinkNode(elem);
3078
 
 
3079
 
    if (elem->type == XML_TEXT_NODE) {
3080
 
        if (cur->type == XML_TEXT_NODE) {
3081
 
            xmlChar *tmp;
3082
 
 
3083
 
            tmp = xmlStrdup(elem->content);
3084
 
            tmp = xmlStrcat(tmp, cur->content);
3085
 
            xmlNodeSetContent(cur, tmp);
3086
 
            xmlFree(tmp);
3087
 
            xmlFreeNode(elem);
3088
 
            return(cur);
3089
 
        }
3090
 
        if ((cur->prev != NULL) && (cur->prev->type == XML_TEXT_NODE) &&
3091
 
            (cur->name == cur->prev->name)) {
3092
 
            xmlNodeAddContent(cur->prev, elem->content);
3093
 
            xmlFreeNode(elem);
3094
 
            return(cur->prev);
3095
 
        }
3096
 
    } else if (elem->type == XML_ATTRIBUTE_NODE) {
3097
 
                return xmlAddPropSibling(cur->prev, cur, elem);
3098
 
    }
3099
 
 
3100
 
    if (elem->doc != cur->doc) {
3101
 
        xmlSetTreeDoc(elem, cur->doc);
3102
 
    }
3103
 
    elem->parent = cur->parent;
3104
 
    elem->next = cur;
3105
 
    elem->prev = cur->prev;
3106
 
    cur->prev = elem;
3107
 
    if (elem->prev != NULL)
3108
 
        elem->prev->next = elem;
3109
 
    if ((elem->parent != NULL) && (elem->parent->children == cur)) {
3110
 
                elem->parent->children = elem;
3111
 
    }
3112
 
    return(elem);
3113
 
}
3114
 
#endif /* LIBXML_TREE_ENABLED */
3115
 
 
3116
 
/**
3117
 
 * xmlAddSibling:
3118
 
 * @cur:  the child node
3119
 
 * @elem:  the new node
3120
 
 *
3121
 
 * Add a new element @elem to the list of siblings of @cur
3122
 
 * merging adjacent TEXT nodes (@elem may be freed)
3123
 
 * If the new element was already inserted in a document it is
3124
 
 * first unlinked from its existing context.
3125
 
 *
3126
 
 * Returns the new element or NULL in case of error.
3127
 
 */
3128
 
xmlNodePtr
3129
 
xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
3130
 
    xmlNodePtr parent;
3131
 
 
3132
 
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3133
 
#ifdef DEBUG_TREE
3134
 
        xmlGenericError(xmlGenericErrorContext,
3135
 
                "xmlAddSibling : cur == NULL\n");
3136
 
#endif
3137
 
        return(NULL);
3138
 
    }
3139
 
 
3140
 
    if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) {
3141
 
#ifdef DEBUG_TREE
3142
 
        xmlGenericError(xmlGenericErrorContext,
3143
 
                "xmlAddSibling : elem == NULL\n");
3144
 
#endif
3145
 
        return(NULL);
3146
 
    }
3147
 
 
3148
 
    if (cur == elem) {
3149
 
#ifdef DEBUG_TREE
3150
 
        xmlGenericError(xmlGenericErrorContext,
3151
 
                "xmlAddSibling : cur == elem\n");
3152
 
#endif
3153
 
        return(NULL);
3154
 
    }
3155
 
 
3156
 
    /*
3157
 
     * Constant time is we can rely on the ->parent->last to find
3158
 
     * the last sibling.
3159
 
     */
3160
 
    if ((cur->type != XML_ATTRIBUTE_NODE) && (cur->parent != NULL) &&
3161
 
        (cur->parent->children != NULL) &&
3162
 
        (cur->parent->last != NULL) &&
3163
 
        (cur->parent->last->next == NULL)) {
3164
 
        cur = cur->parent->last;
3165
 
    } else {
3166
 
        while (cur->next != NULL) cur = cur->next;
3167
 
    }
3168
 
 
3169
 
    xmlUnlinkNode(elem);
3170
 
 
3171
 
    if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE) &&
3172
 
        (cur->name == elem->name)) {
3173
 
        xmlNodeAddContent(cur, elem->content);
3174
 
        xmlFreeNode(elem);
3175
 
        return(cur);
3176
 
    } else if (elem->type == XML_ATTRIBUTE_NODE) {
3177
 
                return xmlAddPropSibling(cur, cur, elem);
3178
 
    }
3179
 
 
3180
 
    if (elem->doc != cur->doc) {
3181
 
        xmlSetTreeDoc(elem, cur->doc);
3182
 
    }
3183
 
    parent = cur->parent;
3184
 
    elem->prev = cur;
3185
 
    elem->next = NULL;
3186
 
    elem->parent = parent;
3187
 
    cur->next = elem;
3188
 
    if (parent != NULL)
3189
 
        parent->last = elem;
3190
 
 
3191
 
    return(elem);
3192
 
}
3193
 
 
3194
 
/**
3195
 
 * xmlAddChildList:
3196
 
 * @parent:  the parent node
3197
 
 * @cur:  the first node in the list
3198
 
 *
3199
 
 * Add a list of node at the end of the child list of the parent
3200
 
 * merging adjacent TEXT nodes (@cur may be freed)
3201
 
 *
3202
 
 * Returns the last child or NULL in case of error.
3203
 
 */
3204
 
xmlNodePtr
3205
 
xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
3206
 
    xmlNodePtr prev;
3207
 
 
3208
 
    if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
3209
 
#ifdef DEBUG_TREE
3210
 
        xmlGenericError(xmlGenericErrorContext,
3211
 
                "xmlAddChildList : parent == NULL\n");
3212
 
#endif
3213
 
        return(NULL);
3214
 
    }
3215
 
 
3216
 
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3217
 
#ifdef DEBUG_TREE
3218
 
        xmlGenericError(xmlGenericErrorContext,
3219
 
                "xmlAddChildList : child == NULL\n");
3220
 
#endif
3221
 
        return(NULL);
3222
 
    }
3223
 
 
3224
 
    if ((cur->doc != NULL) && (parent->doc != NULL) &&
3225
 
        (cur->doc != parent->doc)) {
3226
 
#ifdef DEBUG_TREE
3227
 
        xmlGenericError(xmlGenericErrorContext,
3228
 
                "Elements moved to a different document\n");
3229
 
#endif
3230
 
    }
3231
 
 
3232
 
    /*
3233
 
     * add the first element at the end of the children list.
3234
 
     */
3235
 
 
3236
 
    if (parent->children == NULL) {
3237
 
        parent->children = cur;
3238
 
    } else {
3239
 
        /*
3240
 
         * If cur and parent->last both are TEXT nodes, then merge them.
3241
 
         */
3242
 
        if ((cur->type == XML_TEXT_NODE) &&
3243
 
            (parent->last->type == XML_TEXT_NODE) &&
3244
 
            (cur->name == parent->last->name)) {
3245
 
            xmlNodeAddContent(parent->last, cur->content);
3246
 
            /*
3247
 
             * if it's the only child, nothing more to be done.
3248
 
             */
3249
 
            if (cur->next == NULL) {
3250
 
                xmlFreeNode(cur);
3251
 
                return(parent->last);
3252
 
            }
3253
 
            prev = cur;
3254
 
            cur = cur->next;
3255
 
            xmlFreeNode(prev);
3256
 
        }
3257
 
        prev = parent->last;
3258
 
        prev->next = cur;
3259
 
        cur->prev = prev;
3260
 
    }
3261
 
    while (cur->next != NULL) {
3262
 
        cur->parent = parent;
3263
 
        if (cur->doc != parent->doc) {
3264
 
            xmlSetTreeDoc(cur, parent->doc);
3265
 
        }
3266
 
        cur = cur->next;
3267
 
    }
3268
 
    cur->parent = parent;
3269
 
    /* the parent may not be linked to a doc ! */
3270
 
    if (cur->doc != parent->doc) {
3271
 
        xmlSetTreeDoc(cur, parent->doc);
3272
 
    }
3273
 
    parent->last = cur;
3274
 
 
3275
 
    return(cur);
3276
 
}
3277
 
 
3278
 
/**
3279
 
 * xmlAddChild:
3280
 
 * @parent:  the parent node
3281
 
 * @cur:  the child node
3282
 
 *
3283
 
 * Add a new node to @parent, at the end of the child (or property) list
3284
 
 * merging adjacent TEXT nodes (in which case @cur is freed)
3285
 
 * If the new node is ATTRIBUTE, it is added into properties instead of children.
3286
 
 * If there is an attribute with equal name, it is first destroyed.
3287
 
 *
3288
 
 * Returns the child or NULL in case of error.
3289
 
 */
3290
 
xmlNodePtr
3291
 
xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
3292
 
    xmlNodePtr prev;
3293
 
 
3294
 
    if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
3295
 
#ifdef DEBUG_TREE
3296
 
        xmlGenericError(xmlGenericErrorContext,
3297
 
                "xmlAddChild : parent == NULL\n");
3298
 
#endif
3299
 
        return(NULL);
3300
 
    }
3301
 
 
3302
 
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3303
 
#ifdef DEBUG_TREE
3304
 
        xmlGenericError(xmlGenericErrorContext,
3305
 
                "xmlAddChild : child == NULL\n");
3306
 
#endif
3307
 
        return(NULL);
3308
 
    }
3309
 
 
3310
 
    if (parent == cur) {
3311
 
#ifdef DEBUG_TREE
3312
 
        xmlGenericError(xmlGenericErrorContext,
3313
 
                "xmlAddChild : parent == cur\n");
3314
 
#endif
3315
 
        return(NULL);
3316
 
    }
3317
 
    /*
3318
 
     * If cur is a TEXT node, merge its content with adjacent TEXT nodes
3319
 
     * cur is then freed.
3320
 
     */
3321
 
    if (cur->type == XML_TEXT_NODE) {
3322
 
        if ((parent->type == XML_TEXT_NODE) &&
3323
 
            (parent->content != NULL) &&
3324
 
            (parent->name == cur->name)) {
3325
 
            xmlNodeAddContent(parent, cur->content);
3326
 
            xmlFreeNode(cur);
3327
 
            return(parent);
3328
 
        }
3329
 
        if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) &&
3330
 
            (parent->last->name == cur->name) &&
3331
 
            (parent->last != cur)) {
3332
 
            xmlNodeAddContent(parent->last, cur->content);
3333
 
            xmlFreeNode(cur);
3334
 
            return(parent->last);
3335
 
        }
3336
 
    }
3337
 
 
3338
 
    /*
3339
 
     * add the new element at the end of the children list.
3340
 
     */
3341
 
    prev = cur->parent;
3342
 
    cur->parent = parent;
3343
 
    if (cur->doc != parent->doc) {
3344
 
        xmlSetTreeDoc(cur, parent->doc);
3345
 
    }
3346
 
    /* this check prevents a loop on tree-traversions if a developer
3347
 
     * tries to add a node to its parent multiple times
3348
 
     */
3349
 
    if (prev == parent)
3350
 
        return(cur);
3351
 
 
3352
 
    /*
3353
 
     * Coalescing
3354
 
     */
3355
 
    if ((parent->type == XML_TEXT_NODE) &&
3356
 
        (parent->content != NULL) &&
3357
 
        (parent != cur)) {
3358
 
        xmlNodeAddContent(parent, cur->content);
3359
 
        xmlFreeNode(cur);
3360
 
        return(parent);
3361
 
    }
3362
 
    if (cur->type == XML_ATTRIBUTE_NODE) {
3363
 
                if (parent->type != XML_ELEMENT_NODE)
3364
 
                        return(NULL);
3365
 
        if (parent->properties != NULL) {
3366
 
            /* check if an attribute with the same name exists */
3367
 
            xmlAttrPtr lastattr;
3368
 
 
3369
 
            if (cur->ns == NULL)
3370
 
                lastattr = xmlHasNsProp(parent, cur->name, NULL);
3371
 
            else
3372
 
                lastattr = xmlHasNsProp(parent, cur->name, cur->ns->href);
3373
 
            if ((lastattr != NULL) && (lastattr != (xmlAttrPtr) cur) && (lastattr->type != XML_ATTRIBUTE_DECL)) {
3374
 
                /* different instance, destroy it (attributes must be unique) */
3375
 
                        xmlUnlinkNode((xmlNodePtr) lastattr);
3376
 
                xmlFreeProp(lastattr);
3377
 
            }
3378
 
                if (lastattr == (xmlAttrPtr) cur)
3379
 
                        return(cur);
3380
 
 
3381
 
        }
3382
 
        if (parent->properties == NULL) {
3383
 
            parent->properties = (xmlAttrPtr) cur;
3384
 
        } else {
3385
 
            /* find the end */
3386
 
            xmlAttrPtr lastattr = parent->properties;
3387
 
            while (lastattr->next != NULL) {
3388
 
                lastattr = lastattr->next;
3389
 
            }
3390
 
            lastattr->next = (xmlAttrPtr) cur;
3391
 
            ((xmlAttrPtr) cur)->prev = lastattr;
3392
 
        }
3393
 
    } else {
3394
 
        if (parent->children == NULL) {
3395
 
            parent->children = cur;
3396
 
            parent->last = cur;
3397
 
        } else {
3398
 
            prev = parent->last;
3399
 
            prev->next = cur;
3400
 
            cur->prev = prev;
3401
 
            parent->last = cur;
3402
 
        }
3403
 
    }
3404
 
    return(cur);
3405
 
}
3406
 
 
3407
 
/**
3408
 
 * xmlGetLastChild:
3409
 
 * @parent:  the parent node
3410
 
 *
3411
 
 * Search the last child of a node.
3412
 
 * Returns the last child or NULL if none.
3413
 
 */
3414
 
xmlNodePtr
3415
 
xmlGetLastChild(xmlNodePtr parent) {
3416
 
    if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) {
3417
 
#ifdef DEBUG_TREE
3418
 
        xmlGenericError(xmlGenericErrorContext,
3419
 
                "xmlGetLastChild : parent == NULL\n");
3420
 
#endif
3421
 
        return(NULL);
3422
 
    }
3423
 
    return(parent->last);
3424
 
}
3425
 
 
3426
 
#ifdef LIBXML_TREE_ENABLED
3427
 
/*
3428
 
 * 5 interfaces from DOM ElementTraversal
3429
 
 */
3430
 
 
3431
 
/**
3432
 
 * xmlChildElementCount:
3433
 
 * @parent: the parent node
3434
 
 *
3435
 
 * Finds the current number of child nodes of that element which are
3436
 
 * element nodes.
3437
 
 * Note the handling of entities references is different than in
3438
 
 * the W3C DOM element traversal spec since we don't have back reference
3439
 
 * from entities content to entities references.
3440
 
 *
3441
 
 * Returns the count of element child or 0 if not available
3442
 
 */
3443
 
unsigned long
3444
 
xmlChildElementCount(xmlNodePtr parent) {
3445
 
    unsigned long ret = 0;
3446
 
    xmlNodePtr cur = NULL;
3447
 
 
3448
 
    if (parent == NULL)
3449
 
        return(0);
3450
 
    switch (parent->type) {
3451
 
        case XML_ELEMENT_NODE:
3452
 
        case XML_ENTITY_NODE:
3453
 
        case XML_DOCUMENT_NODE:
3454
 
        case XML_HTML_DOCUMENT_NODE:
3455
 
            cur = parent->children;
3456
 
            break;
3457
 
        default:
3458
 
            return(0);
3459
 
    }
3460
 
    while (cur != NULL) {
3461
 
        if (cur->type == XML_ELEMENT_NODE)
3462
 
            ret++;
3463
 
        cur = cur->next;
3464
 
    }
3465
 
    return(ret);
3466
 
}
3467
 
 
3468
 
/**
3469
 
 * xmlFirstElementChild:
3470
 
 * @parent: the parent node
3471
 
 *
3472
 
 * Finds the first child node of that element which is a Element node
3473
 
 * Note the handling of entities references is different than in
3474
 
 * the W3C DOM element traversal spec since we don't have back reference
3475
 
 * from entities content to entities references.
3476
 
 *
3477
 
 * Returns the first element child or NULL if not available
3478
 
 */
3479
 
xmlNodePtr
3480
 
xmlFirstElementChild(xmlNodePtr parent) {
3481
 
    xmlNodePtr cur = NULL;
3482
 
 
3483
 
    if (parent == NULL)
3484
 
        return(NULL);
3485
 
    switch (parent->type) {
3486
 
        case XML_ELEMENT_NODE:
3487
 
        case XML_ENTITY_NODE:
3488
 
        case XML_DOCUMENT_NODE:
3489
 
        case XML_HTML_DOCUMENT_NODE:
3490
 
            cur = parent->children;
3491
 
            break;
3492
 
        default:
3493
 
            return(NULL);
3494
 
    }
3495
 
    while (cur != NULL) {
3496
 
        if (cur->type == XML_ELEMENT_NODE)
3497
 
            return(cur);
3498
 
        cur = cur->next;
3499
 
    }
3500
 
    return(NULL);
3501
 
}
3502
 
 
3503
 
/**
3504
 
 * xmlLastElementChild:
3505
 
 * @parent: the parent node
3506
 
 *
3507
 
 * Finds the last child node of that element which is a Element node
3508
 
 * Note the handling of entities references is different than in
3509
 
 * the W3C DOM element traversal spec since we don't have back reference
3510
 
 * from entities content to entities references.
3511
 
 *
3512
 
 * Returns the last element child or NULL if not available
3513
 
 */
3514
 
xmlNodePtr
3515
 
xmlLastElementChild(xmlNodePtr parent) {
3516
 
    xmlNodePtr cur = NULL;
3517
 
 
3518
 
    if (parent == NULL)
3519
 
        return(NULL);
3520
 
    switch (parent->type) {
3521
 
        case XML_ELEMENT_NODE:
3522
 
        case XML_ENTITY_NODE:
3523
 
        case XML_DOCUMENT_NODE:
3524
 
        case XML_HTML_DOCUMENT_NODE:
3525
 
            cur = parent->last;
3526
 
            break;
3527
 
        default:
3528
 
            return(NULL);
3529
 
    }
3530
 
    while (cur != NULL) {
3531
 
        if (cur->type == XML_ELEMENT_NODE)
3532
 
            return(cur);
3533
 
        cur = cur->prev;
3534
 
    }
3535
 
    return(NULL);
3536
 
}
3537
 
 
3538
 
/**
3539
 
 * xmlPreviousElementSibling:
3540
 
 * @node: the current node
3541
 
 *
3542
 
 * Finds the first closest previous sibling of the node which is an
3543
 
 * element node.
3544
 
 * Note the handling of entities references is different than in
3545
 
 * the W3C DOM element traversal spec since we don't have back reference
3546
 
 * from entities content to entities references.
3547
 
 *
3548
 
 * Returns the previous element sibling or NULL if not available
3549
 
 */
3550
 
xmlNodePtr
3551
 
xmlPreviousElementSibling(xmlNodePtr node) {
3552
 
    if (node == NULL)
3553
 
        return(NULL);
3554
 
    switch (node->type) {
3555
 
        case XML_ELEMENT_NODE:
3556
 
        case XML_TEXT_NODE:
3557
 
        case XML_CDATA_SECTION_NODE:
3558
 
        case XML_ENTITY_REF_NODE:
3559
 
        case XML_ENTITY_NODE:
3560
 
        case XML_PI_NODE:
3561
 
        case XML_COMMENT_NODE:
3562
 
        case XML_XINCLUDE_START:
3563
 
        case XML_XINCLUDE_END:
3564
 
            node = node->prev;
3565
 
            break;
3566
 
        default:
3567
 
            return(NULL);
3568
 
    }
3569
 
    while (node != NULL) {
3570
 
        if (node->type == XML_ELEMENT_NODE)
3571
 
            return(node);
3572
 
        node = node->prev;
3573
 
    }
3574
 
    return(NULL);
3575
 
}
3576
 
 
3577
 
/**
3578
 
 * xmlNextElementSibling:
3579
 
 * @node: the current node
3580
 
 *
3581
 
 * Finds the first closest next sibling of the node which is an
3582
 
 * element node.
3583
 
 * Note the handling of entities references is different than in
3584
 
 * the W3C DOM element traversal spec since we don't have back reference
3585
 
 * from entities content to entities references.
3586
 
 *
3587
 
 * Returns the next element sibling or NULL if not available
3588
 
 */
3589
 
xmlNodePtr
3590
 
xmlNextElementSibling(xmlNodePtr node) {
3591
 
    if (node == NULL)
3592
 
        return(NULL);
3593
 
    switch (node->type) {
3594
 
        case XML_ELEMENT_NODE:
3595
 
        case XML_TEXT_NODE:
3596
 
        case XML_CDATA_SECTION_NODE:
3597
 
        case XML_ENTITY_REF_NODE:
3598
 
        case XML_ENTITY_NODE:
3599
 
        case XML_PI_NODE:
3600
 
        case XML_COMMENT_NODE:
3601
 
        case XML_DTD_NODE:
3602
 
        case XML_XINCLUDE_START:
3603
 
        case XML_XINCLUDE_END:
3604
 
            node = node->next;
3605
 
            break;
3606
 
        default:
3607
 
            return(NULL);
3608
 
    }
3609
 
    while (node != NULL) {
3610
 
        if (node->type == XML_ELEMENT_NODE)
3611
 
            return(node);
3612
 
        node = node->next;
3613
 
    }
3614
 
    return(NULL);
3615
 
}
3616
 
 
3617
 
#endif /* LIBXML_TREE_ENABLED */
3618
 
 
3619
 
/**
3620
 
 * xmlFreeNodeList:
3621
 
 * @cur:  the first node in the list
3622
 
 *
3623
 
 * Free a node and all its siblings, this is a recursive behaviour, all
3624
 
 * the children are freed too.
3625
 
 */
3626
 
void
3627
 
xmlFreeNodeList(xmlNodePtr cur) {
3628
 
    xmlNodePtr next;
3629
 
    xmlDictPtr dict = NULL;
3630
 
 
3631
 
    if (cur == NULL) return;
3632
 
    if (cur->type == XML_NAMESPACE_DECL) {
3633
 
        xmlFreeNsList((xmlNsPtr) cur);
3634
 
        return;
3635
 
    }
3636
 
    if ((cur->type == XML_DOCUMENT_NODE) ||
3637
 
#ifdef LIBXML_DOCB_ENABLED
3638
 
        (cur->type == XML_DOCB_DOCUMENT_NODE) ||
3639
 
#endif
3640
 
        (cur->type == XML_HTML_DOCUMENT_NODE)) {
3641
 
        xmlFreeDoc((xmlDocPtr) cur);
3642
 
        return;
3643
 
    }
3644
 
    if (cur->doc != NULL) dict = cur->doc->dict;
3645
 
    while (cur != NULL) {
3646
 
        next = cur->next;
3647
 
        if (cur->type != XML_DTD_NODE) {
3648
 
 
3649
 
            if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
3650
 
                xmlDeregisterNodeDefaultValue(cur);
3651
 
 
3652
 
            if ((cur->children != NULL) &&
3653
 
                (cur->type != XML_ENTITY_REF_NODE))
3654
 
                xmlFreeNodeList(cur->children);
3655
 
            if (((cur->type == XML_ELEMENT_NODE) ||
3656
 
                 (cur->type == XML_XINCLUDE_START) ||
3657
 
                 (cur->type == XML_XINCLUDE_END)) &&
3658
 
                (cur->properties != NULL))
3659
 
                xmlFreePropList(cur->properties);
3660
 
            if ((cur->type != XML_ELEMENT_NODE) &&
3661
 
                (cur->type != XML_XINCLUDE_START) &&
3662
 
                (cur->type != XML_XINCLUDE_END) &&
3663
 
                (cur->type != XML_ENTITY_REF_NODE) &&
3664
 
                (cur->content != (xmlChar *) &(cur->properties))) {
3665
 
                DICT_FREE(cur->content)
3666
 
            }
3667
 
            if (((cur->type == XML_ELEMENT_NODE) ||
3668
 
                 (cur->type == XML_XINCLUDE_START) ||
3669
 
                 (cur->type == XML_XINCLUDE_END)) &&
3670
 
                (cur->nsDef != NULL))
3671
 
                xmlFreeNsList(cur->nsDef);
3672
 
 
3673
 
            /*
3674
 
             * When a node is a text node or a comment, it uses a global static
3675
 
             * variable for the name of the node.
3676
 
             * Otherwise the node name might come from the document's
3677
 
             * dictionnary
3678
 
             */
3679
 
            if ((cur->name != NULL) &&
3680
 
                (cur->type != XML_TEXT_NODE) &&
3681
 
                (cur->type != XML_COMMENT_NODE))
3682
 
                DICT_FREE(cur->name)
3683
 
            xmlFree(cur);
3684
 
        }
3685
 
        cur = next;
3686
 
    }
3687
 
}
3688
 
 
3689
 
/**
3690
 
 * xmlFreeNode:
3691
 
 * @cur:  the node
3692
 
 *
3693
 
 * Free a node, this is a recursive behaviour, all the children are freed too.
3694
 
 * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
3695
 
 */
3696
 
void
3697
 
xmlFreeNode(xmlNodePtr cur) {
3698
 
    xmlDictPtr dict = NULL;
3699
 
 
3700
 
    if (cur == NULL) return;
3701
 
 
3702
 
    /* use xmlFreeDtd for DTD nodes */
3703
 
    if (cur->type == XML_DTD_NODE) {
3704
 
        xmlFreeDtd((xmlDtdPtr) cur);
3705
 
        return;
3706
 
    }
3707
 
    if (cur->type == XML_NAMESPACE_DECL) {
3708
 
        xmlFreeNs((xmlNsPtr) cur);
3709
 
        return;
3710
 
    }
3711
 
    if (cur->type == XML_ATTRIBUTE_NODE) {
3712
 
        xmlFreeProp((xmlAttrPtr) cur);
3713
 
        return;
3714
 
    }
3715
 
 
3716
 
    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
3717
 
        xmlDeregisterNodeDefaultValue(cur);
3718
 
 
3719
 
    if (cur->doc != NULL) dict = cur->doc->dict;
3720
 
 
3721
 
    if (cur->type == XML_ENTITY_DECL) {
3722
 
        xmlEntityPtr ent = (xmlEntityPtr) cur;
3723
 
        DICT_FREE(ent->SystemID);
3724
 
        DICT_FREE(ent->ExternalID);
3725
 
    }
3726
 
    if ((cur->children != NULL) &&
3727
 
        (cur->type != XML_ENTITY_REF_NODE))
3728
 
        xmlFreeNodeList(cur->children);
3729
 
    if (((cur->type == XML_ELEMENT_NODE) ||
3730
 
         (cur->type == XML_XINCLUDE_START) ||
3731
 
         (cur->type == XML_XINCLUDE_END)) &&
3732
 
        (cur->properties != NULL))
3733
 
        xmlFreePropList(cur->properties);
3734
 
    if ((cur->type != XML_ELEMENT_NODE) &&
3735
 
        (cur->content != NULL) &&
3736
 
        (cur->type != XML_ENTITY_REF_NODE) &&
3737
 
        (cur->type != XML_XINCLUDE_END) &&
3738
 
        (cur->type != XML_XINCLUDE_START) &&
3739
 
        (cur->content != (xmlChar *) &(cur->properties))) {
3740
 
        DICT_FREE(cur->content)
3741
 
    }
3742
 
 
3743
 
    /*
3744
 
     * When a node is a text node or a comment, it uses a global static
3745
 
     * variable for the name of the node.
3746
 
     * Otherwise the node name might come from the document's dictionnary
3747
 
     */
3748
 
    if ((cur->name != NULL) &&
3749
 
        (cur->type != XML_TEXT_NODE) &&
3750
 
        (cur->type != XML_COMMENT_NODE))
3751
 
        DICT_FREE(cur->name)
3752
 
 
3753
 
    if (((cur->type == XML_ELEMENT_NODE) ||
3754
 
         (cur->type == XML_XINCLUDE_START) ||
3755
 
         (cur->type == XML_XINCLUDE_END)) &&
3756
 
        (cur->nsDef != NULL))
3757
 
        xmlFreeNsList(cur->nsDef);
3758
 
    xmlFree(cur);
3759
 
}
3760
 
 
3761
 
/**
3762
 
 * xmlUnlinkNode:
3763
 
 * @cur:  the node
3764
 
 *
3765
 
 * Unlink a node from it's current context, the node is not freed
3766
 
 * If one need to free the node, use xmlFreeNode() routine after the
3767
 
 * unlink to discard it.
3768
 
 * Note that namespace nodes can't be unlinked as they do not have
3769
 
 * pointer to their parent.
3770
 
 */
3771
 
void
3772
 
xmlUnlinkNode(xmlNodePtr cur) {
3773
 
    if (cur == NULL) {
3774
 
#ifdef DEBUG_TREE
3775
 
        xmlGenericError(xmlGenericErrorContext,
3776
 
                "xmlUnlinkNode : node == NULL\n");
3777
 
#endif
3778
 
        return;
3779
 
    }
3780
 
    if (cur->type == XML_NAMESPACE_DECL)
3781
 
        return;
3782
 
    if (cur->type == XML_DTD_NODE) {
3783
 
        xmlDocPtr doc;
3784
 
        doc = cur->doc;
3785
 
        if (doc != NULL) {
3786
 
            if (doc->intSubset == (xmlDtdPtr) cur)
3787
 
                doc->intSubset = NULL;
3788
 
            if (doc->extSubset == (xmlDtdPtr) cur)
3789
 
                doc->extSubset = NULL;
3790
 
        }
3791
 
    }
3792
 
    if (cur->type == XML_ENTITY_DECL) {
3793
 
        xmlDocPtr doc;
3794
 
        doc = cur->doc;
3795
 
        if (doc != NULL) {
3796
 
            if (doc->intSubset != NULL) {
3797
 
                if (xmlHashLookup(doc->intSubset->entities, cur->name) == cur)
3798
 
                    xmlHashRemoveEntry(doc->intSubset->entities, cur->name,
3799
 
                                       NULL);
3800
 
                if (xmlHashLookup(doc->intSubset->pentities, cur->name) == cur)
3801
 
                    xmlHashRemoveEntry(doc->intSubset->pentities, cur->name,
3802
 
                                       NULL);
3803
 
            }
3804
 
            if (doc->extSubset != NULL) {
3805
 
                if (xmlHashLookup(doc->extSubset->entities, cur->name) == cur)
3806
 
                    xmlHashRemoveEntry(doc->extSubset->entities, cur->name,
3807
 
                                       NULL);
3808
 
                if (xmlHashLookup(doc->extSubset->pentities, cur->name) == cur)
3809
 
                    xmlHashRemoveEntry(doc->extSubset->pentities, cur->name,
3810
 
                                       NULL);
3811
 
            }
3812
 
        }
3813
 
    }
3814
 
    if (cur->parent != NULL) {
3815
 
        xmlNodePtr parent;
3816
 
        parent = cur->parent;
3817
 
        if (cur->type == XML_ATTRIBUTE_NODE) {
3818
 
            if (parent->properties == (xmlAttrPtr) cur)
3819
 
                parent->properties = ((xmlAttrPtr) cur)->next;
3820
 
        } else {
3821
 
            if (parent->children == cur)
3822
 
                parent->children = cur->next;
3823
 
            if (parent->last == cur)
3824
 
                parent->last = cur->prev;
3825
 
        }
3826
 
        cur->parent = NULL;
3827
 
    }
3828
 
    if (cur->next != NULL)
3829
 
        cur->next->prev = cur->prev;
3830
 
    if (cur->prev != NULL)
3831
 
        cur->prev->next = cur->next;
3832
 
    cur->next = cur->prev = NULL;
3833
 
}
3834
 
 
3835
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
3836
 
/**
3837
 
 * xmlReplaceNode:
3838
 
 * @old:  the old node
3839
 
 * @cur:  the node
3840
 
 *
3841
 
 * Unlink the old node from its current context, prune the new one
3842
 
 * at the same place. If @cur was already inserted in a document it is
3843
 
 * first unlinked from its existing context.
3844
 
 *
3845
 
 * Returns the @old node
3846
 
 */
3847
 
xmlNodePtr
3848
 
xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
3849
 
    if (old == cur) return(NULL);
3850
 
    if ((old == NULL) || (old->type == XML_NAMESPACE_DECL) ||
3851
 
        (old->parent == NULL)) {
3852
 
#ifdef DEBUG_TREE
3853
 
        xmlGenericError(xmlGenericErrorContext,
3854
 
                "xmlReplaceNode : old == NULL or without parent\n");
3855
 
#endif
3856
 
        return(NULL);
3857
 
    }
3858
 
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) {
3859
 
        xmlUnlinkNode(old);
3860
 
        return(old);
3861
 
    }
3862
 
    if (cur == old) {
3863
 
        return(old);
3864
 
    }
3865
 
    if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) {
3866
 
#ifdef DEBUG_TREE
3867
 
        xmlGenericError(xmlGenericErrorContext,
3868
 
                "xmlReplaceNode : Trying to replace attribute node with other node type\n");
3869
 
#endif
3870
 
        return(old);
3871
 
    }
3872
 
    if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) {
3873
 
#ifdef DEBUG_TREE
3874
 
        xmlGenericError(xmlGenericErrorContext,
3875
 
                "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");
3876
 
#endif
3877
 
        return(old);
3878
 
    }
3879
 
    xmlUnlinkNode(cur);
3880
 
    xmlSetTreeDoc(cur, old->doc);
3881
 
    cur->parent = old->parent;
3882
 
    cur->next = old->next;
3883
 
    if (cur->next != NULL)
3884
 
        cur->next->prev = cur;
3885
 
    cur->prev = old->prev;
3886
 
    if (cur->prev != NULL)
3887
 
        cur->prev->next = cur;
3888
 
    if (cur->parent != NULL) {
3889
 
        if (cur->type == XML_ATTRIBUTE_NODE) {
3890
 
            if (cur->parent->properties == (xmlAttrPtr)old)
3891
 
                cur->parent->properties = ((xmlAttrPtr) cur);
3892
 
        } else {
3893
 
            if (cur->parent->children == old)
3894
 
                cur->parent->children = cur;
3895
 
            if (cur->parent->last == old)
3896
 
                cur->parent->last = cur;
3897
 
        }
3898
 
    }
3899
 
    old->next = old->prev = NULL;
3900
 
    old->parent = NULL;
3901
 
    return(old);
3902
 
}
3903
 
#endif /* LIBXML_TREE_ENABLED */
3904
 
 
3905
 
/************************************************************************
3906
 
 *                                                                      *
3907
 
 *              Copy operations                                         *
3908
 
 *                                                                      *
3909
 
 ************************************************************************/
3910
 
 
3911
 
/**
3912
 
 * xmlCopyNamespace:
3913
 
 * @cur:  the namespace
3914
 
 *
3915
 
 * Do a copy of the namespace.
3916
 
 *
3917
 
 * Returns: a new #xmlNsPtr, or NULL in case of error.
3918
 
 */
3919
 
xmlNsPtr
3920
 
xmlCopyNamespace(xmlNsPtr cur) {
3921
 
    xmlNsPtr ret;
3922
 
 
3923
 
    if (cur == NULL) return(NULL);
3924
 
    switch (cur->type) {
3925
 
        case XML_LOCAL_NAMESPACE:
3926
 
            ret = xmlNewNs(NULL, cur->href, cur->prefix);
3927
 
            break;
3928
 
        default:
3929
 
#ifdef DEBUG_TREE
3930
 
            xmlGenericError(xmlGenericErrorContext,
3931
 
                    "xmlCopyNamespace: invalid type %d\n", cur->type);
3932
 
#endif
3933
 
            return(NULL);
3934
 
    }
3935
 
    return(ret);
3936
 
}
3937
 
 
3938
 
/**
3939
 
 * xmlCopyNamespaceList:
3940
 
 * @cur:  the first namespace
3941
 
 *
3942
 
 * Do a copy of an namespace list.
3943
 
 *
3944
 
 * Returns: a new #xmlNsPtr, or NULL in case of error.
3945
 
 */
3946
 
xmlNsPtr
3947
 
xmlCopyNamespaceList(xmlNsPtr cur) {
3948
 
    xmlNsPtr ret = NULL;
3949
 
    xmlNsPtr p = NULL,q;
3950
 
 
3951
 
    while (cur != NULL) {
3952
 
        q = xmlCopyNamespace(cur);
3953
 
        if (p == NULL) {
3954
 
            ret = p = q;
3955
 
        } else {
3956
 
            p->next = q;
3957
 
            p = q;
3958
 
        }
3959
 
        cur = cur->next;
3960
 
    }
3961
 
    return(ret);
3962
 
}
3963
 
 
3964
 
static xmlNodePtr
3965
 
xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
3966
 
 
3967
 
static xmlAttrPtr
3968
 
xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) {
3969
 
    xmlAttrPtr ret;
3970
 
 
3971
 
    if (cur == NULL) return(NULL);
3972
 
    if ((target != NULL) && (target->type != XML_ELEMENT_NODE))
3973
 
        return(NULL);
3974
 
    if (target != NULL)
3975
 
        ret = xmlNewDocProp(target->doc, cur->name, NULL);
3976
 
    else if (doc != NULL)
3977
 
        ret = xmlNewDocProp(doc, cur->name, NULL);
3978
 
    else if (cur->parent != NULL)
3979
 
        ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL);
3980
 
    else if (cur->children != NULL)
3981
 
        ret = xmlNewDocProp(cur->children->doc, cur->name, NULL);
3982
 
    else
3983
 
        ret = xmlNewDocProp(NULL, cur->name, NULL);
3984
 
    if (ret == NULL) return(NULL);
3985
 
    ret->parent = target;
3986
 
 
3987
 
    if ((cur->ns != NULL) && (target != NULL)) {
3988
 
      xmlNsPtr ns;
3989
 
 
3990
 
      ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
3991
 
      if (ns == NULL) {
3992
 
        /*
3993
 
         * Humm, we are copying an element whose namespace is defined
3994
 
         * out of the new tree scope. Search it in the original tree
3995
 
         * and add it at the top of the new tree
3996
 
         */
3997
 
        ns = xmlSearchNs(cur->doc, cur->parent, cur->ns->prefix);
3998
 
        if (ns != NULL) {
3999
 
          xmlNodePtr root = target;
4000
 
          xmlNodePtr pred = NULL;
4001
 
 
4002
 
          while (root->parent != NULL) {
4003
 
            pred = root;
4004
 
            root = root->parent;
4005
 
          }
4006
 
          if (root == (xmlNodePtr) target->doc) {
4007
 
            /* correct possibly cycling above the document elt */
4008
 
            root = pred;
4009
 
          }
4010
 
          ret->ns = xmlNewNs(root, ns->href, ns->prefix);
4011
 
        }
4012
 
      } else {
4013
 
        /*
4014
 
         * we have to find something appropriate here since
4015
 
         * we cant be sure, that the namespce we found is identified
4016
 
         * by the prefix
4017
 
         */
4018
 
        if (xmlStrEqual(ns->href, cur->ns->href)) {
4019
 
          /* this is the nice case */
4020
 
          ret->ns = ns;
4021
 
        } else {
4022
 
          /*
4023
 
           * we are in trouble: we need a new reconcilied namespace.
4024
 
           * This is expensive
4025
 
           */
4026
 
          ret->ns = xmlNewReconciliedNs(target->doc, target, cur->ns);
4027
 
        }
4028
 
      }
4029
 
 
4030
 
    } else
4031
 
        ret->ns = NULL;
4032
 
 
4033
 
    if (cur->children != NULL) {
4034
 
        xmlNodePtr tmp;
4035
 
 
4036
 
        ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret);
4037
 
        ret->last = NULL;
4038
 
        tmp = ret->children;
4039
 
        while (tmp != NULL) {
4040
 
            /* tmp->parent = (xmlNodePtr)ret; */
4041
 
            if (tmp->next == NULL)
4042
 
                ret->last = tmp;
4043
 
            tmp = tmp->next;
4044
 
        }
4045
 
    }
4046
 
    /*
4047
 
     * Try to handle IDs
4048
 
     */
4049
 
    if ((target!= NULL) && (cur!= NULL) &&
4050
 
        (target->doc != NULL) && (cur->doc != NULL) &&
4051
 
        (cur->doc->ids != NULL) && (cur->parent != NULL)) {
4052
 
        if (xmlIsID(cur->doc, cur->parent, cur)) {
4053
 
            xmlChar *id;
4054
 
 
4055
 
            id = xmlNodeListGetString(cur->doc, cur->children, 1);
4056
 
            if (id != NULL) {
4057
 
                xmlAddID(NULL, target->doc, id, ret);
4058
 
                xmlFree(id);
4059
 
            }
4060
 
        }
4061
 
    }
4062
 
    return(ret);
4063
 
}
4064
 
 
4065
 
/**
4066
 
 * xmlCopyProp:
4067
 
 * @target:  the element where the attribute will be grafted
4068
 
 * @cur:  the attribute
4069
 
 *
4070
 
 * Do a copy of the attribute.
4071
 
 *
4072
 
 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4073
 
 */
4074
 
xmlAttrPtr
4075
 
xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
4076
 
        return xmlCopyPropInternal(NULL, target, cur);
4077
 
}
4078
 
 
4079
 
/**
4080
 
 * xmlCopyPropList:
4081
 
 * @target:  the element where the attributes will be grafted
4082
 
 * @cur:  the first attribute
4083
 
 *
4084
 
 * Do a copy of an attribute list.
4085
 
 *
4086
 
 * Returns: a new #xmlAttrPtr, or NULL in case of error.
4087
 
 */
4088
 
xmlAttrPtr
4089
 
xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
4090
 
    xmlAttrPtr ret = NULL;
4091
 
    xmlAttrPtr p = NULL,q;
4092
 
 
4093
 
    if ((target != NULL) && (target->type != XML_ELEMENT_NODE))
4094
 
        return(NULL);
4095
 
    while (cur != NULL) {
4096
 
        q = xmlCopyProp(target, cur);
4097
 
        if (q == NULL)
4098
 
            return(NULL);
4099
 
        if (p == NULL) {
4100
 
            ret = p = q;
4101
 
        } else {
4102
 
            p->next = q;
4103
 
            q->prev = p;
4104
 
            p = q;
4105
 
        }
4106
 
        cur = cur->next;
4107
 
    }
4108
 
    return(ret);
4109
 
}
4110
 
 
4111
 
/*
4112
 
 * NOTE about the CopyNode operations !
4113
 
 *
4114
 
 * They are split into external and internal parts for one
4115
 
 * tricky reason: namespaces. Doing a direct copy of a node
4116
 
 * say RPM:Copyright without changing the namespace pointer to
4117
 
 * something else can produce stale links. One way to do it is
4118
 
 * to keep a reference counter but this doesn't work as soon
4119
 
 * as one move the element or the subtree out of the scope of
4120
 
 * the existing namespace. The actual solution seems to add
4121
 
 * a copy of the namespace at the top of the copied tree if
4122
 
 * not available in the subtree.
4123
 
 * Hence two functions, the public front-end call the inner ones
4124
 
 * The argument "recursive" normally indicates a recursive copy
4125
 
 * of the node with values 0 (no) and 1 (yes).  For XInclude,
4126
 
 * however, we allow a value of 2 to indicate copy properties and
4127
 
 * namespace info, but don't recurse on children.
4128
 
 */
4129
 
 
4130
 
static xmlNodePtr
4131
 
xmlStaticCopyNode(const xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
4132
 
                  int extended) {
4133
 
    xmlNodePtr ret;
4134
 
 
4135
 
    if (node == NULL) return(NULL);
4136
 
    switch (node->type) {
4137
 
        case XML_TEXT_NODE:
4138
 
        case XML_CDATA_SECTION_NODE:
4139
 
        case XML_ELEMENT_NODE:
4140
 
        case XML_DOCUMENT_FRAG_NODE:
4141
 
        case XML_ENTITY_REF_NODE:
4142
 
        case XML_ENTITY_NODE:
4143
 
        case XML_PI_NODE:
4144
 
        case XML_COMMENT_NODE:
4145
 
        case XML_XINCLUDE_START:
4146
 
        case XML_XINCLUDE_END:
4147
 
            break;
4148
 
        case XML_ATTRIBUTE_NODE:
4149
 
                return((xmlNodePtr) xmlCopyPropInternal(doc, parent, (xmlAttrPtr) node));
4150
 
        case XML_NAMESPACE_DECL:
4151
 
            return((xmlNodePtr) xmlCopyNamespaceList((xmlNsPtr) node));
4152
 
 
4153
 
        case XML_DOCUMENT_NODE:
4154
 
        case XML_HTML_DOCUMENT_NODE:
4155
 
#ifdef LIBXML_DOCB_ENABLED
4156
 
        case XML_DOCB_DOCUMENT_NODE:
4157
 
#endif
4158
 
#ifdef LIBXML_TREE_ENABLED
4159
 
            return((xmlNodePtr) xmlCopyDoc((xmlDocPtr) node, extended));
4160
 
#endif /* LIBXML_TREE_ENABLED */
4161
 
        case XML_DOCUMENT_TYPE_NODE:
4162
 
        case XML_NOTATION_NODE:
4163
 
        case XML_DTD_NODE:
4164
 
        case XML_ELEMENT_DECL:
4165
 
        case XML_ATTRIBUTE_DECL:
4166
 
        case XML_ENTITY_DECL:
4167
 
            return(NULL);
4168
 
    }
4169
 
 
4170
 
    /*
4171
 
     * Allocate a new node and fill the fields.
4172
 
     */
4173
 
    ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
4174
 
    if (ret == NULL) {
4175
 
        xmlTreeErrMemory("copying node");
4176
 
        return(NULL);
4177
 
    }
4178
 
    memset(ret, 0, sizeof(xmlNode));
4179
 
    ret->type = node->type;
4180
 
 
4181
 
    ret->doc = doc;
4182
 
    ret->parent = parent;
4183
 
    if (node->name == xmlStringText)
4184
 
        ret->name = xmlStringText;
4185
 
    else if (node->name == xmlStringTextNoenc)
4186
 
        ret->name = xmlStringTextNoenc;
4187
 
    else if (node->name == xmlStringComment)
4188
 
        ret->name = xmlStringComment;
4189
 
    else if (node->name != NULL) {
4190
 
        if ((doc != NULL) && (doc->dict != NULL))
4191
 
            ret->name = xmlDictLookup(doc->dict, node->name, -1);
4192
 
        else
4193
 
            ret->name = xmlStrdup(node->name);
4194
 
    }
4195
 
    if ((node->type != XML_ELEMENT_NODE) &&
4196
 
        (node->content != NULL) &&
4197
 
        (node->type != XML_ENTITY_REF_NODE) &&
4198
 
        (node->type != XML_XINCLUDE_END) &&
4199
 
        (node->type != XML_XINCLUDE_START)) {
4200
 
        ret->content = xmlStrdup(node->content);
4201
 
    }else{
4202
 
      if (node->type == XML_ELEMENT_NODE)
4203
 
        ret->line = node->line;
4204
 
    }
4205
 
    if (parent != NULL) {
4206
 
        xmlNodePtr tmp;
4207
 
 
4208
 
        /*
4209
 
         * this is a tricky part for the node register thing:
4210
 
         * in case ret does get coalesced in xmlAddChild
4211
 
         * the deregister-node callback is called; so we register ret now already
4212
 
         */
4213
 
        if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
4214
 
            xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
4215
 
 
4216
 
        tmp = xmlAddChild(parent, ret);
4217
 
        /* node could have coalesced */
4218
 
        if (tmp != ret)
4219
 
            return(tmp);
4220
 
    }
4221
 
 
4222
 
    if (!extended)
4223
 
        goto out;
4224
 
    if (((node->type == XML_ELEMENT_NODE) ||
4225
 
         (node->type == XML_XINCLUDE_START)) && (node->nsDef != NULL))
4226
 
        ret->nsDef = xmlCopyNamespaceList(node->nsDef);
4227
 
 
4228
 
    if (node->ns != NULL) {
4229
 
        xmlNsPtr ns;
4230
 
 
4231
 
        ns = xmlSearchNs(doc, ret, node->ns->prefix);
4232
 
        if (ns == NULL) {
4233
 
            /*
4234
 
             * Humm, we are copying an element whose namespace is defined
4235
 
             * out of the new tree scope. Search it in the original tree
4236
 
             * and add it at the top of the new tree
4237
 
             */
4238
 
            ns = xmlSearchNs(node->doc, node, node->ns->prefix);
4239
 
            if (ns != NULL) {
4240
 
                xmlNodePtr root = ret;
4241
 
 
4242
 
                while (root->parent != NULL) root = root->parent;
4243
 
                ret->ns = xmlNewNs(root, ns->href, ns->prefix);
4244
 
                } else {
4245
 
                        ret->ns = xmlNewReconciliedNs(doc, ret, node->ns);
4246
 
            }
4247
 
        } else {
4248
 
            /*
4249
 
             * reference the existing namespace definition in our own tree.
4250
 
             */
4251
 
            ret->ns = ns;
4252
 
        }
4253
 
    }
4254
 
    if (((node->type == XML_ELEMENT_NODE) ||
4255
 
         (node->type == XML_XINCLUDE_START)) && (node->properties != NULL))
4256
 
        ret->properties = xmlCopyPropList(ret, node->properties);
4257
 
    if (node->type == XML_ENTITY_REF_NODE) {
4258
 
        if ((doc == NULL) || (node->doc != doc)) {
4259
 
            /*
4260
 
             * The copied node will go into a separate document, so
4261
 
             * to avoid dangling references to the ENTITY_DECL node
4262
 
             * we cannot keep the reference. Try to find it in the
4263
 
             * target document.
4264
 
             */
4265
 
            ret->children = (xmlNodePtr) xmlGetDocEntity(doc, ret->name);
4266
 
        } else {
4267
 
            ret->children = node->children;
4268
 
        }
4269
 
        ret->last = ret->children;
4270
 
    } else if ((node->children != NULL) && (extended != 2)) {
4271
 
        ret->children = xmlStaticCopyNodeList(node->children, doc, ret);
4272
 
        UPDATE_LAST_CHILD_AND_PARENT(ret)
4273
 
    }
4274
 
 
4275
 
out:
4276
 
    /* if parent != NULL we already registered the node above */
4277
 
    if ((parent == NULL) &&
4278
 
        ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)))
4279
 
        xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
4280
 
    return(ret);
4281
 
}
4282
 
 
4283
 
static xmlNodePtr
4284
 
xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
4285
 
    xmlNodePtr ret = NULL;
4286
 
    xmlNodePtr p = NULL,q;
4287
 
 
4288
 
    while (node != NULL) {
4289
 
#ifdef LIBXML_TREE_ENABLED
4290
 
        if (node->type == XML_DTD_NODE ) {
4291
 
            if (doc == NULL) {
4292
 
                node = node->next;
4293
 
                continue;
4294
 
            }
4295
 
            if (doc->intSubset == NULL) {
4296
 
                q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node );
4297
 
                q->doc = doc;
4298
 
                q->parent = parent;
4299
 
                doc->intSubset = (xmlDtdPtr) q;
4300
 
                xmlAddChild(parent, q);
4301
 
            } else {
4302
 
                q = (xmlNodePtr) doc->intSubset;
4303
 
                xmlAddChild(parent, q);
4304
 
            }
4305
 
        } else
4306
 
#endif /* LIBXML_TREE_ENABLED */
4307
 
            q = xmlStaticCopyNode(node, doc, parent, 1);
4308
 
        if (ret == NULL) {
4309
 
            q->prev = NULL;
4310
 
            ret = p = q;
4311
 
        } else if (p != q) {
4312
 
        /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */
4313
 
            p->next = q;
4314
 
            q->prev = p;
4315
 
            p = q;
4316
 
        }
4317
 
        node = node->next;
4318
 
    }
4319
 
    return(ret);
4320
 
}
4321
 
 
4322
 
/**
4323
 
 * xmlCopyNode:
4324
 
 * @node:  the node
4325
 
 * @extended:   if 1 do a recursive copy (properties, namespaces and children
4326
 
 *                      when applicable)
4327
 
 *              if 2 copy properties and namespaces (when applicable)
4328
 
 *
4329
 
 * Do a copy of the node.
4330
 
 *
4331
 
 * Returns: a new #xmlNodePtr, or NULL in case of error.
4332
 
 */
4333
 
xmlNodePtr
4334
 
xmlCopyNode(const xmlNodePtr node, int extended) {
4335
 
    xmlNodePtr ret;
4336
 
 
4337
 
    ret = xmlStaticCopyNode(node, NULL, NULL, extended);
4338
 
    return(ret);
4339
 
}
4340
 
 
4341
 
/**
4342
 
 * xmlDocCopyNode:
4343
 
 * @node:  the node
4344
 
 * @doc:  the document
4345
 
 * @extended:   if 1 do a recursive copy (properties, namespaces and children
4346
 
 *                      when applicable)
4347
 
 *              if 2 copy properties and namespaces (when applicable)
4348
 
 *
4349
 
 * Do a copy of the node to a given document.
4350
 
 *
4351
 
 * Returns: a new #xmlNodePtr, or NULL in case of error.
4352
 
 */
4353
 
xmlNodePtr
4354
 
xmlDocCopyNode(const xmlNodePtr node, xmlDocPtr doc, int extended) {
4355
 
    xmlNodePtr ret;
4356
 
 
4357
 
    ret = xmlStaticCopyNode(node, doc, NULL, extended);
4358
 
    return(ret);
4359
 
}
4360
 
 
4361
 
/**
4362
 
 * xmlDocCopyNodeList:
4363
 
 * @doc: the target document
4364
 
 * @node:  the first node in the list.
4365
 
 *
4366
 
 * Do a recursive copy of the node list.
4367
 
 *
4368
 
 * Returns: a new #xmlNodePtr, or NULL in case of error.
4369
 
 */
4370
 
xmlNodePtr xmlDocCopyNodeList(xmlDocPtr doc, const xmlNodePtr node) {
4371
 
    xmlNodePtr ret = xmlStaticCopyNodeList(node, doc, NULL);
4372
 
    return(ret);
4373
 
}
4374
 
 
4375
 
/**
4376
 
 * xmlCopyNodeList:
4377
 
 * @node:  the first node in the list.
4378
 
 *
4379
 
 * Do a recursive copy of the node list.
4380
 
 * Use xmlDocCopyNodeList() if possible to ensure string interning.
4381
 
 *
4382
 
 * Returns: a new #xmlNodePtr, or NULL in case of error.
4383
 
 */
4384
 
xmlNodePtr xmlCopyNodeList(const xmlNodePtr node) {
4385
 
    xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
4386
 
    return(ret);
4387
 
}
4388
 
 
4389
 
#if defined(LIBXML_TREE_ENABLED)
4390
 
/**
4391
 
 * xmlCopyDtd:
4392
 
 * @dtd:  the dtd
4393
 
 *
4394
 
 * Do a copy of the dtd.
4395
 
 *
4396
 
 * Returns: a new #xmlDtdPtr, or NULL in case of error.
4397
 
 */
4398
 
xmlDtdPtr
4399
 
xmlCopyDtd(xmlDtdPtr dtd) {
4400
 
    xmlDtdPtr ret;
4401
 
    xmlNodePtr cur, p = NULL, q;
4402
 
 
4403
 
    if (dtd == NULL) return(NULL);
4404
 
    ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
4405
 
    if (ret == NULL) return(NULL);
4406
 
    if (dtd->entities != NULL)
4407
 
        ret->entities = (void *) xmlCopyEntitiesTable(
4408
 
                            (xmlEntitiesTablePtr) dtd->entities);
4409
 
    if (dtd->notations != NULL)
4410
 
        ret->notations = (void *) xmlCopyNotationTable(
4411
 
                            (xmlNotationTablePtr) dtd->notations);
4412
 
    if (dtd->elements != NULL)
4413
 
        ret->elements = (void *) xmlCopyElementTable(
4414
 
                            (xmlElementTablePtr) dtd->elements);
4415
 
    if (dtd->attributes != NULL)
4416
 
        ret->attributes = (void *) xmlCopyAttributeTable(
4417
 
                            (xmlAttributeTablePtr) dtd->attributes);
4418
 
    if (dtd->pentities != NULL)
4419
 
        ret->pentities = (void *) xmlCopyEntitiesTable(
4420
 
                            (xmlEntitiesTablePtr) dtd->pentities);
4421
 
 
4422
 
    cur = dtd->children;
4423
 
    while (cur != NULL) {
4424
 
        q = NULL;
4425
 
 
4426
 
        if (cur->type == XML_ENTITY_DECL) {
4427
 
            xmlEntityPtr tmp = (xmlEntityPtr) cur;
4428
 
            switch (tmp->etype) {
4429
 
                case XML_INTERNAL_GENERAL_ENTITY:
4430
 
                case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
4431
 
                case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
4432
 
                    q = (xmlNodePtr) xmlGetEntityFromDtd(ret, tmp->name);
4433
 
                    break;
4434
 
                case XML_INTERNAL_PARAMETER_ENTITY:
4435
 
                case XML_EXTERNAL_PARAMETER_ENTITY:
4436
 
                    q = (xmlNodePtr)
4437
 
                        xmlGetParameterEntityFromDtd(ret, tmp->name);
4438
 
                    break;
4439
 
                case XML_INTERNAL_PREDEFINED_ENTITY:
4440
 
                    break;
4441
 
            }
4442
 
        } else if (cur->type == XML_ELEMENT_DECL) {
4443
 
            xmlElementPtr tmp = (xmlElementPtr) cur;
4444
 
            q = (xmlNodePtr)
4445
 
                xmlGetDtdQElementDesc(ret, tmp->name, tmp->prefix);
4446
 
        } else if (cur->type == XML_ATTRIBUTE_DECL) {
4447
 
            xmlAttributePtr tmp = (xmlAttributePtr) cur;
4448
 
            q = (xmlNodePtr)
4449
 
                xmlGetDtdQAttrDesc(ret, tmp->elem, tmp->name, tmp->prefix);
4450
 
        } else if (cur->type == XML_COMMENT_NODE) {
4451
 
            q = xmlCopyNode(cur, 0);
4452
 
        }
4453
 
 
4454
 
        if (q == NULL) {
4455
 
            cur = cur->next;
4456
 
            continue;
4457
 
        }
4458
 
 
4459
 
        if (p == NULL)
4460
 
            ret->children = q;
4461
 
        else
4462
 
            p->next = q;
4463
 
 
4464
 
        q->prev = p;
4465
 
        q->parent = (xmlNodePtr) ret;
4466
 
        q->next = NULL;
4467
 
        ret->last = q;
4468
 
        p = q;
4469
 
        cur = cur->next;
4470
 
    }
4471
 
 
4472
 
    return(ret);
4473
 
}
4474
 
#endif
4475
 
 
4476
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
4477
 
/**
4478
 
 * xmlCopyDoc:
4479
 
 * @doc:  the document
4480
 
 * @recursive:  if not zero do a recursive copy.
4481
 
 *
4482
 
 * Do a copy of the document info. If recursive, the content tree will
4483
 
 * be copied too as well as DTD, namespaces and entities.
4484
 
 *
4485
 
 * Returns: a new #xmlDocPtr, or NULL in case of error.
4486
 
 */
4487
 
xmlDocPtr
4488
 
xmlCopyDoc(xmlDocPtr doc, int recursive) {
4489
 
    xmlDocPtr ret;
4490
 
 
4491
 
    if (doc == NULL) return(NULL);
4492
 
    ret = xmlNewDoc(doc->version);
4493
 
    if (ret == NULL) return(NULL);
4494
 
    if (doc->name != NULL)
4495
 
        ret->name = xmlMemStrdup(doc->name);
4496
 
    if (doc->encoding != NULL)
4497
 
        ret->encoding = xmlStrdup(doc->encoding);
4498
 
    if (doc->URL != NULL)
4499
 
        ret->URL = xmlStrdup(doc->URL);
4500
 
    ret->charset = doc->charset;
4501
 
    ret->compression = doc->compression;
4502
 
    ret->standalone = doc->standalone;
4503
 
    if (!recursive) return(ret);
4504
 
 
4505
 
    ret->last = NULL;
4506
 
    ret->children = NULL;
4507
 
#ifdef LIBXML_TREE_ENABLED
4508
 
    if (doc->intSubset != NULL) {
4509
 
        ret->intSubset = xmlCopyDtd(doc->intSubset);
4510
 
        xmlSetTreeDoc((xmlNodePtr)ret->intSubset, ret);
4511
 
        ret->intSubset->parent = ret;
4512
 
    }
4513
 
#endif
4514
 
    if (doc->oldNs != NULL)
4515
 
        ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
4516
 
    if (doc->children != NULL) {
4517
 
        xmlNodePtr tmp;
4518
 
 
4519
 
        ret->children = xmlStaticCopyNodeList(doc->children, ret,
4520
 
                                               (xmlNodePtr)ret);
4521
 
        ret->last = NULL;
4522
 
        tmp = ret->children;
4523
 
        while (tmp != NULL) {
4524
 
            if (tmp->next == NULL)
4525
 
                ret->last = tmp;
4526
 
            tmp = tmp->next;
4527
 
        }
4528
 
    }
4529
 
    return(ret);
4530
 
}
4531
 
#endif /* LIBXML_TREE_ENABLED */
4532
 
 
4533
 
/************************************************************************
4534
 
 *                                                                      *
4535
 
 *              Content access functions                                *
4536
 
 *                                                                      *
4537
 
 ************************************************************************/
4538
 
 
4539
 
/**
4540
 
 * xmlGetLineNoInternal:
4541
 
 * @node: valid node
4542
 
 * @depth: used to limit any risk of recursion
4543
 
 *
4544
 
 * Get line number of @node.
4545
 
 * Try to override the limitation of lines being store in 16 bits ints
4546
 
 *
4547
 
 * Returns the line number if successful, -1 otherwise
4548
 
 */
4549
 
static long
4550
 
xmlGetLineNoInternal(xmlNodePtr node, int depth)
4551
 
{
4552
 
    long result = -1;
4553
 
 
4554
 
    if (depth >= 5)
4555
 
        return(-1);
4556
 
 
4557
 
    if (!node)
4558
 
        return result;
4559
 
    if ((node->type == XML_ELEMENT_NODE) ||
4560
 
        (node->type == XML_TEXT_NODE) ||
4561
 
        (node->type == XML_COMMENT_NODE) ||
4562
 
        (node->type == XML_PI_NODE)) {
4563
 
        if (node->line == 65535) {
4564
 
            if ((node->type == XML_TEXT_NODE) && (node->psvi != NULL))
4565
 
                result = (long) node->psvi;
4566
 
            else if ((node->type == XML_ELEMENT_NODE) &&
4567
 
                     (node->children != NULL))
4568
 
                result = xmlGetLineNoInternal(node->children, depth + 1);
4569
 
            else if (node->next != NULL)
4570
 
                result = xmlGetLineNoInternal(node->next, depth + 1);
4571
 
            else if (node->prev != NULL)
4572
 
                result = xmlGetLineNoInternal(node->prev, depth + 1);
4573
 
        }
4574
 
        if ((result == -1) || (result == 65535))
4575
 
            result = (long) node->line;
4576
 
    } else if ((node->prev != NULL) &&
4577
 
             ((node->prev->type == XML_ELEMENT_NODE) ||
4578
 
              (node->prev->type == XML_TEXT_NODE) ||
4579
 
              (node->prev->type == XML_COMMENT_NODE) ||
4580
 
              (node->prev->type == XML_PI_NODE)))
4581
 
        result = xmlGetLineNoInternal(node->prev, depth + 1);
4582
 
    else if ((node->parent != NULL) &&
4583
 
             (node->parent->type == XML_ELEMENT_NODE))
4584
 
        result = xmlGetLineNoInternal(node->parent, depth + 1);
4585
 
 
4586
 
    return result;
4587
 
}
4588
 
 
4589
 
/**
4590
 
 * xmlGetLineNo:
4591
 
 * @node: valid node
4592
 
 *
4593
 
 * Get line number of @node.
4594
 
 * Try to override the limitation of lines being store in 16 bits ints
4595
 
 * if XML_PARSE_BIG_LINES parser option was used
4596
 
 *
4597
 
 * Returns the line number if successful, -1 otherwise
4598
 
 */
4599
 
long
4600
 
xmlGetLineNo(xmlNodePtr node)
4601
 
{
4602
 
    return(xmlGetLineNoInternal(node, 0));
4603
 
}
4604
 
 
4605
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
4606
 
/**
4607
 
 * xmlGetNodePath:
4608
 
 * @node: a node
4609
 
 *
4610
 
 * Build a structure based Path for the given node
4611
 
 *
4612
 
 * Returns the new path or NULL in case of error. The caller must free
4613
 
 *     the returned string
4614
 
 */
4615
 
xmlChar *
4616
 
xmlGetNodePath(xmlNodePtr node)
4617
 
{
4618
 
    xmlNodePtr cur, tmp, next;
4619
 
    xmlChar *buffer = NULL, *temp;
4620
 
    size_t buf_len;
4621
 
    xmlChar *buf;
4622
 
    const char *sep;
4623
 
    const char *name;
4624
 
    char nametemp[100];
4625
 
    int occur = 0, generic;
4626
 
 
4627
 
    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
4628
 
        return (NULL);
4629
 
 
4630
 
    buf_len = 500;
4631
 
    buffer = (xmlChar *) xmlMallocAtomic(buf_len * sizeof(xmlChar));
4632
 
    if (buffer == NULL) {
4633
 
        xmlTreeErrMemory("getting node path");
4634
 
        return (NULL);
4635
 
    }
4636
 
    buf = (xmlChar *) xmlMallocAtomic(buf_len * sizeof(xmlChar));
4637
 
    if (buf == NULL) {
4638
 
        xmlTreeErrMemory("getting node path");
4639
 
        xmlFree(buffer);
4640
 
        return (NULL);
4641
 
    }
4642
 
 
4643
 
    buffer[0] = 0;
4644
 
    cur = node;
4645
 
    do {
4646
 
        name = "";
4647
 
        sep = "?";
4648
 
        occur = 0;
4649
 
        if ((cur->type == XML_DOCUMENT_NODE) ||
4650
 
            (cur->type == XML_HTML_DOCUMENT_NODE)) {
4651
 
            if (buffer[0] == '/')
4652
 
                break;
4653
 
            sep = "/";
4654
 
            next = NULL;
4655
 
        } else if (cur->type == XML_ELEMENT_NODE) {
4656
 
            generic = 0;
4657
 
            sep = "/";
4658
 
            name = (const char *) cur->name;
4659
 
            if (cur->ns) {
4660
 
                if (cur->ns->prefix != NULL) {
4661
 
                    snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",
4662
 
                        (char *)cur->ns->prefix, (char *)cur->name);
4663
 
                    nametemp[sizeof(nametemp) - 1] = 0;
4664
 
                    name = nametemp;
4665
 
                } else {
4666
 
                    /*
4667
 
                    * We cannot express named elements in the default
4668
 
                    * namespace, so use "*".
4669
 
                    */
4670
 
                    generic = 1;
4671
 
                    name = "*";
4672
 
                }
4673
 
            }
4674
 
            next = cur->parent;
4675
 
 
4676
 
            /*
4677
 
             * Thumbler index computation
4678
 
             * TODO: the ocurence test seems bogus for namespaced names
4679
 
             */
4680
 
            tmp = cur->prev;
4681
 
            while (tmp != NULL) {
4682
 
                if ((tmp->type == XML_ELEMENT_NODE) &&
4683
 
                    (generic ||
4684
 
                     (xmlStrEqual(cur->name, tmp->name) &&
4685
 
                     ((tmp->ns == cur->ns) ||
4686
 
                      ((tmp->ns != NULL) && (cur->ns != NULL) &&
4687
 
                       (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))
4688
 
                    occur++;
4689
 
                tmp = tmp->prev;
4690
 
            }
4691
 
            if (occur == 0) {
4692
 
                tmp = cur->next;
4693
 
                while (tmp != NULL && occur == 0) {
4694
 
                    if ((tmp->type == XML_ELEMENT_NODE) &&
4695
 
                        (generic ||
4696
 
                         (xmlStrEqual(cur->name, tmp->name) &&
4697
 
                         ((tmp->ns == cur->ns) ||
4698
 
                          ((tmp->ns != NULL) && (cur->ns != NULL) &&
4699
 
                           (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))
4700
 
                        occur++;
4701
 
                    tmp = tmp->next;
4702
 
                }
4703
 
                if (occur != 0)
4704
 
                    occur = 1;
4705
 
            } else
4706
 
                occur++;
4707
 
        } else if (cur->type == XML_COMMENT_NODE) {
4708
 
            sep = "/";
4709
 
            name = "comment()";
4710
 
            next = cur->parent;
4711
 
 
4712
 
            /*
4713
 
             * Thumbler index computation
4714
 
             */
4715
 
            tmp = cur->prev;
4716
 
            while (tmp != NULL) {
4717
 
                if (tmp->type == XML_COMMENT_NODE)
4718
 
                    occur++;
4719
 
                tmp = tmp->prev;
4720
 
            }
4721
 
            if (occur == 0) {
4722
 
                tmp = cur->next;
4723
 
                while (tmp != NULL && occur == 0) {
4724
 
                  if (tmp->type == XML_COMMENT_NODE)
4725
 
                    occur++;
4726
 
                    tmp = tmp->next;
4727
 
                }
4728
 
                if (occur != 0)
4729
 
                    occur = 1;
4730
 
            } else
4731
 
                occur++;
4732
 
        } else if ((cur->type == XML_TEXT_NODE) ||
4733
 
                   (cur->type == XML_CDATA_SECTION_NODE)) {
4734
 
            sep = "/";
4735
 
            name = "text()";
4736
 
            next = cur->parent;
4737
 
 
4738
 
            /*
4739
 
             * Thumbler index computation
4740
 
             */
4741
 
            tmp = cur->prev;
4742
 
            while (tmp != NULL) {
4743
 
                if ((tmp->type == XML_TEXT_NODE) ||
4744
 
                    (tmp->type == XML_CDATA_SECTION_NODE))
4745
 
                    occur++;
4746
 
                tmp = tmp->prev;
4747
 
            }
4748
 
            /*
4749
 
            * Evaluate if this is the only text- or CDATA-section-node;
4750
 
            * if yes, then we'll get "text()", otherwise "text()[1]".
4751
 
            */
4752
 
            if (occur == 0) {
4753
 
                tmp = cur->next;
4754
 
                while (tmp != NULL) {
4755
 
                    if ((tmp->type == XML_TEXT_NODE) ||
4756
 
                        (tmp->type == XML_CDATA_SECTION_NODE))
4757
 
                    {
4758
 
                        occur = 1;
4759
 
                        break;
4760
 
                    }
4761
 
                    tmp = tmp->next;
4762
 
                }
4763
 
            } else
4764
 
                occur++;
4765
 
        } else if (cur->type == XML_PI_NODE) {
4766
 
            sep = "/";
4767
 
            snprintf(nametemp, sizeof(nametemp) - 1,
4768
 
                     "processing-instruction('%s')", (char *)cur->name);
4769
 
            nametemp[sizeof(nametemp) - 1] = 0;
4770
 
            name = nametemp;
4771
 
 
4772
 
            next = cur->parent;
4773
 
 
4774
 
            /*
4775
 
             * Thumbler index computation
4776
 
             */
4777
 
            tmp = cur->prev;
4778
 
            while (tmp != NULL) {
4779
 
                if ((tmp->type == XML_PI_NODE) &&
4780
 
                    (xmlStrEqual(cur->name, tmp->name)))
4781
 
                    occur++;
4782
 
                tmp = tmp->prev;
4783
 
            }
4784
 
            if (occur == 0) {
4785
 
                tmp = cur->next;
4786
 
                while (tmp != NULL && occur == 0) {
4787
 
                    if ((tmp->type == XML_PI_NODE) &&
4788
 
                        (xmlStrEqual(cur->name, tmp->name)))
4789
 
                        occur++;
4790
 
                    tmp = tmp->next;
4791
 
                }
4792
 
                if (occur != 0)
4793
 
                    occur = 1;
4794
 
            } else
4795
 
                occur++;
4796
 
 
4797
 
        } else if (cur->type == XML_ATTRIBUTE_NODE) {
4798
 
            sep = "/@";
4799
 
            name = (const char *) (((xmlAttrPtr) cur)->name);
4800
 
            if (cur->ns) {
4801
 
                if (cur->ns->prefix != NULL)
4802
 
                    snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",
4803
 
                        (char *)cur->ns->prefix, (char *)cur->name);
4804
 
                else
4805
 
                    snprintf(nametemp, sizeof(nametemp) - 1, "%s",
4806
 
                        (char *)cur->name);
4807
 
                nametemp[sizeof(nametemp) - 1] = 0;
4808
 
                name = nametemp;
4809
 
            }
4810
 
            next = ((xmlAttrPtr) cur)->parent;
4811
 
        } else {
4812
 
            next = cur->parent;
4813
 
        }
4814
 
 
4815
 
        /*
4816
 
         * Make sure there is enough room
4817
 
         */
4818
 
        if (xmlStrlen(buffer) + sizeof(nametemp) + 20 > buf_len) {
4819
 
            buf_len =
4820
 
                2 * buf_len + xmlStrlen(buffer) + sizeof(nametemp) + 20;
4821
 
            temp = (xmlChar *) xmlRealloc(buffer, buf_len);
4822
 
            if (temp == NULL) {
4823
 
                xmlTreeErrMemory("getting node path");
4824
 
                xmlFree(buf);
4825
 
                xmlFree(buffer);
4826
 
                return (NULL);
4827
 
            }
4828
 
            buffer = temp;
4829
 
            temp = (xmlChar *) xmlRealloc(buf, buf_len);
4830
 
            if (temp == NULL) {
4831
 
                xmlTreeErrMemory("getting node path");
4832
 
                xmlFree(buf);
4833
 
                xmlFree(buffer);
4834
 
                return (NULL);
4835
 
            }
4836
 
            buf = temp;
4837
 
        }
4838
 
        if (occur == 0)
4839
 
            snprintf((char *) buf, buf_len, "%s%s%s",
4840
 
                     sep, name, (char *) buffer);
4841
 
        else
4842
 
            snprintf((char *) buf, buf_len, "%s%s[%d]%s",
4843
 
                     sep, name, occur, (char *) buffer);
4844
 
        snprintf((char *) buffer, buf_len, "%s", (char *)buf);
4845
 
        cur = next;
4846
 
    } while (cur != NULL);
4847
 
    xmlFree(buf);
4848
 
    return (buffer);
4849
 
}
4850
 
#endif /* LIBXML_TREE_ENABLED */
4851
 
 
4852
 
/**
4853
 
 * xmlDocGetRootElement:
4854
 
 * @doc:  the document
4855
 
 *
4856
 
 * Get the root element of the document (doc->children is a list
4857
 
 * containing possibly comments, PIs, etc ...).
4858
 
 *
4859
 
 * Returns the #xmlNodePtr for the root or NULL
4860
 
 */
4861
 
xmlNodePtr
4862
 
xmlDocGetRootElement(xmlDocPtr doc) {
4863
 
    xmlNodePtr ret;
4864
 
 
4865
 
    if (doc == NULL) return(NULL);
4866
 
    ret = doc->children;
4867
 
    while (ret != NULL) {
4868
 
        if (ret->type == XML_ELEMENT_NODE)
4869
 
            return(ret);
4870
 
        ret = ret->next;
4871
 
    }
4872
 
    return(ret);
4873
 
}
4874
 
 
4875
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
4876
 
/**
4877
 
 * xmlDocSetRootElement:
4878
 
 * @doc:  the document
4879
 
 * @root:  the new document root element, if root is NULL no action is taken,
4880
 
 *         to remove a node from a document use xmlUnlinkNode(root) instead.
4881
 
 *
4882
 
 * Set the root element of the document (doc->children is a list
4883
 
 * containing possibly comments, PIs, etc ...).
4884
 
 *
4885
 
 * Returns the old root element if any was found, NULL if root was NULL
4886
 
 */
4887
 
xmlNodePtr
4888
 
xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
4889
 
    xmlNodePtr old = NULL;
4890
 
 
4891
 
    if (doc == NULL) return(NULL);
4892
 
    if ((root == NULL) || (root->type == XML_NAMESPACE_DECL))
4893
 
        return(NULL);
4894
 
    xmlUnlinkNode(root);
4895
 
    xmlSetTreeDoc(root, doc);
4896
 
    root->parent = (xmlNodePtr) doc;
4897
 
    old = doc->children;
4898
 
    while (old != NULL) {
4899
 
        if (old->type == XML_ELEMENT_NODE)
4900
 
            break;
4901
 
        old = old->next;
4902
 
    }
4903
 
    if (old == NULL) {
4904
 
        if (doc->children == NULL) {
4905
 
            doc->children = root;
4906
 
            doc->last = root;
4907
 
        } else {
4908
 
            xmlAddSibling(doc->children, root);
4909
 
        }
4910
 
    } else {
4911
 
        xmlReplaceNode(old, root);
4912
 
    }
4913
 
    return(old);
4914
 
}
4915
 
#endif
4916
 
 
4917
 
#if defined(LIBXML_TREE_ENABLED)
4918
 
/**
4919
 
 * xmlNodeSetLang:
4920
 
 * @cur:  the node being changed
4921
 
 * @lang:  the language description
4922
 
 *
4923
 
 * Set the language of a node, i.e. the values of the xml:lang
4924
 
 * attribute.
4925
 
 */
4926
 
void
4927
 
xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
4928
 
    xmlNsPtr ns;
4929
 
 
4930
 
    if (cur == NULL) return;
4931
 
    switch(cur->type) {
4932
 
        case XML_TEXT_NODE:
4933
 
        case XML_CDATA_SECTION_NODE:
4934
 
        case XML_COMMENT_NODE:
4935
 
        case XML_DOCUMENT_NODE:
4936
 
        case XML_DOCUMENT_TYPE_NODE:
4937
 
        case XML_DOCUMENT_FRAG_NODE:
4938
 
        case XML_NOTATION_NODE:
4939
 
        case XML_HTML_DOCUMENT_NODE:
4940
 
        case XML_DTD_NODE:
4941
 
        case XML_ELEMENT_DECL:
4942
 
        case XML_ATTRIBUTE_DECL:
4943
 
        case XML_ENTITY_DECL:
4944
 
        case XML_PI_NODE:
4945
 
        case XML_ENTITY_REF_NODE:
4946
 
        case XML_ENTITY_NODE:
4947
 
        case XML_NAMESPACE_DECL:
4948
 
#ifdef LIBXML_DOCB_ENABLED
4949
 
        case XML_DOCB_DOCUMENT_NODE:
4950
 
#endif
4951
 
        case XML_XINCLUDE_START:
4952
 
        case XML_XINCLUDE_END:
4953
 
            return;
4954
 
        case XML_ELEMENT_NODE:
4955
 
        case XML_ATTRIBUTE_NODE:
4956
 
            break;
4957
 
    }
4958
 
    ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
4959
 
    if (ns == NULL)
4960
 
        return;
4961
 
    xmlSetNsProp(cur, ns, BAD_CAST "lang", lang);
4962
 
}
4963
 
#endif /* LIBXML_TREE_ENABLED */
4964
 
 
4965
 
/**
4966
 
 * xmlNodeGetLang:
4967
 
 * @cur:  the node being checked
4968
 
 *
4969
 
 * Searches the language of a node, i.e. the values of the xml:lang
4970
 
 * attribute or the one carried by the nearest ancestor.
4971
 
 *
4972
 
 * Returns a pointer to the lang value, or NULL if not found
4973
 
 *     It's up to the caller to free the memory with xmlFree().
4974
 
 */
4975
 
xmlChar *
4976
 
xmlNodeGetLang(xmlNodePtr cur) {
4977
 
    xmlChar *lang;
4978
 
 
4979
 
    if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
4980
 
        return(NULL);
4981
 
    while (cur != NULL) {
4982
 
        lang = xmlGetNsProp(cur, BAD_CAST "lang", XML_XML_NAMESPACE);
4983
 
        if (lang != NULL)
4984
 
            return(lang);
4985
 
        cur = cur->parent;
4986
 
    }
4987
 
    return(NULL);
4988
 
}
4989
 
 
4990
 
 
4991
 
#ifdef LIBXML_TREE_ENABLED
4992
 
/**
4993
 
 * xmlNodeSetSpacePreserve:
4994
 
 * @cur:  the node being changed
4995
 
 * @val:  the xml:space value ("0": default, 1: "preserve")
4996
 
 *
4997
 
 * Set (or reset) the space preserving behaviour of a node, i.e. the
4998
 
 * value of the xml:space attribute.
4999
 
 */
5000
 
void
5001
 
xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) {
5002
 
    xmlNsPtr ns;
5003
 
 
5004
 
    if (cur == NULL) return;
5005
 
    switch(cur->type) {
5006
 
        case XML_TEXT_NODE:
5007
 
        case XML_CDATA_SECTION_NODE:
5008
 
        case XML_COMMENT_NODE:
5009
 
        case XML_DOCUMENT_NODE:
5010
 
        case XML_DOCUMENT_TYPE_NODE:
5011
 
        case XML_DOCUMENT_FRAG_NODE:
5012
 
        case XML_NOTATION_NODE:
5013
 
        case XML_HTML_DOCUMENT_NODE:
5014
 
        case XML_DTD_NODE:
5015
 
        case XML_ELEMENT_DECL:
5016
 
        case XML_ATTRIBUTE_DECL:
5017
 
        case XML_ENTITY_DECL:
5018
 
        case XML_PI_NODE:
5019
 
        case XML_ENTITY_REF_NODE:
5020
 
        case XML_ENTITY_NODE:
5021
 
        case XML_NAMESPACE_DECL:
5022
 
        case XML_XINCLUDE_START:
5023
 
        case XML_XINCLUDE_END:
5024
 
#ifdef LIBXML_DOCB_ENABLED
5025
 
        case XML_DOCB_DOCUMENT_NODE:
5026
 
#endif
5027
 
            return;
5028
 
        case XML_ELEMENT_NODE:
5029
 
        case XML_ATTRIBUTE_NODE:
5030
 
            break;
5031
 
    }
5032
 
    ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
5033
 
    if (ns == NULL)
5034
 
        return;
5035
 
    switch (val) {
5036
 
    case 0:
5037
 
        xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "default");
5038
 
        break;
5039
 
    case 1:
5040
 
        xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "preserve");
5041
 
        break;
5042
 
    }
5043
 
}
5044
 
#endif /* LIBXML_TREE_ENABLED */
5045
 
 
5046
 
/**
5047
 
 * xmlNodeGetSpacePreserve:
5048
 
 * @cur:  the node being checked
5049
 
 *
5050
 
 * Searches the space preserving behaviour of a node, i.e. the values
5051
 
 * of the xml:space attribute or the one carried by the nearest
5052
 
 * ancestor.
5053
 
 *
5054
 
 * Returns -1 if xml:space is not inherited, 0 if "default", 1 if "preserve"
5055
 
 */
5056
 
int
5057
 
xmlNodeGetSpacePreserve(xmlNodePtr cur) {
5058
 
    xmlChar *space;
5059
 
 
5060
 
    if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))
5061
 
        return(-1);
5062
 
    while (cur != NULL) {
5063
 
        space = xmlGetNsProp(cur, BAD_CAST "space", XML_XML_NAMESPACE);
5064
 
        if (space != NULL) {
5065
 
            if (xmlStrEqual(space, BAD_CAST "preserve")) {
5066
 
                xmlFree(space);
5067
 
                return(1);
5068
 
            }
5069
 
            if (xmlStrEqual(space, BAD_CAST "default")) {
5070
 
                xmlFree(space);
5071
 
                return(0);
5072
 
            }
5073
 
            xmlFree(space);
5074
 
        }
5075
 
        cur = cur->parent;
5076
 
    }
5077
 
    return(-1);
5078
 
}
5079
 
 
5080
 
#ifdef LIBXML_TREE_ENABLED
5081
 
/**
5082
 
 * xmlNodeSetName:
5083
 
 * @cur:  the node being changed
5084
 
 * @name:  the new tag name
5085
 
 *
5086
 
 * Set (or reset) the name of a node.
5087
 
 */
5088
 
void
5089
 
xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
5090
 
    xmlDocPtr doc;
5091
 
    xmlDictPtr dict;
5092
 
 
5093
 
    if (cur == NULL) return;
5094
 
    if (name == NULL) return;
5095
 
    switch(cur->type) {
5096
 
        case XML_TEXT_NODE:
5097
 
        case XML_CDATA_SECTION_NODE:
5098
 
        case XML_COMMENT_NODE:
5099
 
        case XML_DOCUMENT_TYPE_NODE:
5100
 
        case XML_DOCUMENT_FRAG_NODE:
5101
 
        case XML_NOTATION_NODE:
5102
 
        case XML_HTML_DOCUMENT_NODE:
5103
 
        case XML_NAMESPACE_DECL:
5104
 
        case XML_XINCLUDE_START:
5105
 
        case XML_XINCLUDE_END:
5106
 
#ifdef LIBXML_DOCB_ENABLED
5107
 
        case XML_DOCB_DOCUMENT_NODE:
5108
 
#endif
5109
 
            return;
5110
 
        case XML_ELEMENT_NODE:
5111
 
        case XML_ATTRIBUTE_NODE:
5112
 
        case XML_PI_NODE:
5113
 
        case XML_ENTITY_REF_NODE:
5114
 
        case XML_ENTITY_NODE:
5115
 
        case XML_DTD_NODE:
5116
 
        case XML_DOCUMENT_NODE:
5117
 
        case XML_ELEMENT_DECL:
5118
 
        case XML_ATTRIBUTE_DECL:
5119
 
        case XML_ENTITY_DECL:
5120
 
            break;
5121
 
    }
5122
 
    doc = cur->doc;
5123
 
    if (doc != NULL)
5124
 
        dict = doc->dict;
5125
 
    else
5126
 
        dict = NULL;
5127
 
    if (dict != NULL) {
5128
 
        if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name)))
5129
 
            xmlFree((xmlChar *) cur->name);
5130
 
        cur->name = xmlDictLookup(dict, name, -1);
5131
 
    } else {
5132
 
        if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
5133
 
        cur->name = xmlStrdup(name);
5134
 
    }
5135
 
}
5136
 
#endif
5137
 
 
5138
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
5139
 
/**
5140
 
 * xmlNodeSetBase:
5141
 
 * @cur:  the node being changed
5142
 
 * @uri:  the new base URI
5143
 
 *
5144
 
 * Set (or reset) the base URI of a node, i.e. the value of the
5145
 
 * xml:base attribute.
5146
 
 */
5147
 
void
5148
 
xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) {
5149
 
    xmlNsPtr ns;
5150
 
    xmlChar* fixed;
5151
 
 
5152
 
    if (cur == NULL) return;
5153
 
    switch(cur->type) {
5154
 
        case XML_TEXT_NODE:
5155
 
        case XML_CDATA_SECTION_NODE:
5156
 
        case XML_COMMENT_NODE:
5157
 
        case XML_DOCUMENT_TYPE_NODE:
5158
 
        case XML_DOCUMENT_FRAG_NODE:
5159
 
        case XML_NOTATION_NODE:
5160
 
        case XML_DTD_NODE:
5161
 
        case XML_ELEMENT_DECL:
5162
 
        case XML_ATTRIBUTE_DECL:
5163
 
        case XML_ENTITY_DECL:
5164
 
        case XML_PI_NODE:
5165
 
        case XML_ENTITY_REF_NODE:
5166
 
        case XML_ENTITY_NODE:
5167
 
        case XML_NAMESPACE_DECL:
5168
 
        case XML_XINCLUDE_START:
5169
 
        case XML_XINCLUDE_END:
5170
 
            return;
5171
 
        case XML_ELEMENT_NODE:
5172
 
        case XML_ATTRIBUTE_NODE:
5173
 
            break;
5174
 
        case XML_DOCUMENT_NODE:
5175
 
#ifdef LIBXML_DOCB_ENABLED
5176
 
        case XML_DOCB_DOCUMENT_NODE:
5177
 
#endif
5178
 
        case XML_HTML_DOCUMENT_NODE: {
5179
 
            xmlDocPtr doc = (xmlDocPtr) cur;
5180
 
 
5181
 
            if (doc->URL != NULL)
5182
 
                xmlFree((xmlChar *) doc->URL);
5183
 
            if (uri == NULL)
5184
 
                doc->URL = NULL;
5185
 
            else
5186
 
                doc->URL = xmlPathToURI(uri);
5187
 
            return;
5188
 
        }
5189
 
    }
5190
 
 
5191
 
    ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);
5192
 
    if (ns == NULL)
5193
 
        return;
5194
 
    fixed = xmlPathToURI(uri);
5195
 
    if (fixed != NULL) {
5196
 
        xmlSetNsProp(cur, ns, BAD_CAST "base", fixed);
5197
 
        xmlFree(fixed);
5198
 
    } else {
5199
 
        xmlSetNsProp(cur, ns, BAD_CAST "base", uri);
5200
 
    }
5201
 
}
5202
 
#endif /* LIBXML_TREE_ENABLED */
5203
 
 
5204
 
/**
5205
 
 * xmlNodeGetBase:
5206
 
 * @doc:  the document the node pertains to
5207
 
 * @cur:  the node being checked
5208
 
 *
5209
 
 * Searches for the BASE URL. The code should work on both XML
5210
 
 * and HTML document even if base mechanisms are completely different.
5211
 
 * It returns the base as defined in RFC 2396 sections
5212
 
 * 5.1.1. Base URI within Document Content
5213
 
 * and
5214
 
 * 5.1.2. Base URI from the Encapsulating Entity
5215
 
 * However it does not return the document base (5.1.3), use
5216
 
 * doc->URL in this case
5217
 
 *
5218
 
 * Returns a pointer to the base URL, or NULL if not found
5219
 
 *     It's up to the caller to free the memory with xmlFree().
5220
 
 */
5221
 
xmlChar *
5222
 
xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
5223
 
    xmlChar *oldbase = NULL;
5224
 
    xmlChar *base, *newbase;
5225
 
 
5226
 
    if ((cur == NULL) && (doc == NULL))
5227
 
        return(NULL);
5228
 
    if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
5229
 
        return(NULL);
5230
 
    if (doc == NULL) doc = cur->doc;
5231
 
    if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
5232
 
        cur = doc->children;
5233
 
        while ((cur != NULL) && (cur->name != NULL)) {
5234
 
            if (cur->type != XML_ELEMENT_NODE) {
5235
 
                cur = cur->next;
5236
 
                continue;
5237
 
            }
5238
 
            if (!xmlStrcasecmp(cur->name, BAD_CAST "html")) {
5239
 
                cur = cur->children;
5240
 
                continue;
5241
 
            }
5242
 
            if (!xmlStrcasecmp(cur->name, BAD_CAST "head")) {
5243
 
                cur = cur->children;
5244
 
                continue;
5245
 
            }
5246
 
            if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) {
5247
 
                return(xmlGetProp(cur, BAD_CAST "href"));
5248
 
            }
5249
 
            cur = cur->next;
5250
 
        }
5251
 
        return(NULL);
5252
 
    }
5253
 
    while (cur != NULL) {
5254
 
        if (cur->type == XML_ENTITY_DECL) {
5255
 
            xmlEntityPtr ent = (xmlEntityPtr) cur;
5256
 
            return(xmlStrdup(ent->URI));
5257
 
        }
5258
 
        if (cur->type == XML_ELEMENT_NODE) {
5259
 
            base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
5260
 
            if (base != NULL) {
5261
 
                if (oldbase != NULL) {
5262
 
                    newbase = xmlBuildURI(oldbase, base);
5263
 
                    if (newbase != NULL) {
5264
 
                        xmlFree(oldbase);
5265
 
                        xmlFree(base);
5266
 
                        oldbase = newbase;
5267
 
                    } else {
5268
 
                        xmlFree(oldbase);
5269
 
                        xmlFree(base);
5270
 
                        return(NULL);
5271
 
                    }
5272
 
                } else {
5273
 
                    oldbase = base;
5274
 
                }
5275
 
                if ((!xmlStrncmp(oldbase, BAD_CAST "http://", 7)) ||
5276
 
                    (!xmlStrncmp(oldbase, BAD_CAST "ftp://", 6)) ||
5277
 
                    (!xmlStrncmp(oldbase, BAD_CAST "urn:", 4)))
5278
 
                    return(oldbase);
5279
 
            }
5280
 
        }
5281
 
        cur = cur->parent;
5282
 
    }
5283
 
    if ((doc != NULL) && (doc->URL != NULL)) {
5284
 
        if (oldbase == NULL)
5285
 
            return(xmlStrdup(doc->URL));
5286
 
        newbase = xmlBuildURI(oldbase, doc->URL);
5287
 
        xmlFree(oldbase);
5288
 
        return(newbase);
5289
 
    }
5290
 
    return(oldbase);
5291
 
}
5292
 
 
5293
 
/**
5294
 
 * xmlNodeBufGetContent:
5295
 
 * @buffer:  a buffer
5296
 
 * @cur:  the node being read
5297
 
 *
5298
 
 * Read the value of a node @cur, this can be either the text carried
5299
 
 * directly by this node if it's a TEXT node or the aggregate string
5300
 
 * of the values carried by this node child's (TEXT and ENTITY_REF).
5301
 
 * Entity references are substituted.
5302
 
 * Fills up the buffer @buffer with this value
5303
 
 *
5304
 
 * Returns 0 in case of success and -1 in case of error.
5305
 
 */
5306
 
int
5307
 
xmlNodeBufGetContent(xmlBufferPtr buffer, xmlNodePtr cur)
5308
 
{
5309
 
    xmlBufPtr buf;
5310
 
    int ret;
5311
 
 
5312
 
    if ((cur == NULL) || (buffer == NULL)) return(-1);
5313
 
    buf = xmlBufFromBuffer(buffer);
5314
 
    ret = xmlBufGetNodeContent(buf, cur);
5315
 
    buffer = xmlBufBackToBuffer(buf);
5316
 
    if ((ret < 0) || (buffer == NULL))
5317
 
        return(-1);
5318
 
    return(0);
5319
 
}
5320
 
 
5321
 
/**
5322
 
 * xmlBufGetNodeContent:
5323
 
 * @buf:  a buffer xmlBufPtr
5324
 
 * @cur:  the node being read
5325
 
 *
5326
 
 * Read the value of a node @cur, this can be either the text carried
5327
 
 * directly by this node if it's a TEXT node or the aggregate string
5328
 
 * of the values carried by this node child's (TEXT and ENTITY_REF).
5329
 
 * Entity references are substituted.
5330
 
 * Fills up the buffer @buffer with this value
5331
 
 *
5332
 
 * Returns 0 in case of success and -1 in case of error.
5333
 
 */
5334
 
int
5335
 
xmlBufGetNodeContent(xmlBufPtr buf, xmlNodePtr cur)
5336
 
{
5337
 
    if ((cur == NULL) || (buf == NULL)) return(-1);
5338
 
    switch (cur->type) {
5339
 
        case XML_CDATA_SECTION_NODE:
5340
 
        case XML_TEXT_NODE:
5341
 
            xmlBufCat(buf, cur->content);
5342
 
            break;
5343
 
        case XML_DOCUMENT_FRAG_NODE:
5344
 
        case XML_ELEMENT_NODE:{
5345
 
                xmlNodePtr tmp = cur;
5346
 
 
5347
 
                while (tmp != NULL) {
5348
 
                    switch (tmp->type) {
5349
 
                        case XML_CDATA_SECTION_NODE:
5350
 
                        case XML_TEXT_NODE:
5351
 
                            if (tmp->content != NULL)
5352
 
                                xmlBufCat(buf, tmp->content);
5353
 
                            break;
5354
 
                        case XML_ENTITY_REF_NODE:
5355
 
                            xmlBufGetNodeContent(buf, tmp);
5356
 
                            break;
5357
 
                        default:
5358
 
                            break;
5359
 
                    }
5360
 
                    /*
5361
 
                     * Skip to next node
5362
 
                     */
5363
 
                    if (tmp->children != NULL) {
5364
 
                        if (tmp->children->type != XML_ENTITY_DECL) {
5365
 
                            tmp = tmp->children;
5366
 
                            continue;
5367
 
                        }
5368
 
                    }
5369
 
                    if (tmp == cur)
5370
 
                        break;
5371
 
 
5372
 
                    if (tmp->next != NULL) {
5373
 
                        tmp = tmp->next;
5374
 
                        continue;
5375
 
                    }
5376
 
 
5377
 
                    do {
5378
 
                        tmp = tmp->parent;
5379
 
                        if (tmp == NULL)
5380
 
                            break;
5381
 
                        if (tmp == cur) {
5382
 
                            tmp = NULL;
5383
 
                            break;
5384
 
                        }
5385
 
                        if (tmp->next != NULL) {
5386
 
                            tmp = tmp->next;
5387
 
                            break;
5388
 
                        }
5389
 
                    } while (tmp != NULL);
5390
 
                }
5391
 
                break;
5392
 
            }
5393
 
        case XML_ATTRIBUTE_NODE:{
5394
 
                xmlAttrPtr attr = (xmlAttrPtr) cur;
5395
 
                xmlNodePtr tmp = attr->children;
5396
 
 
5397
 
                while (tmp != NULL) {
5398
 
                    if (tmp->type == XML_TEXT_NODE)
5399
 
                        xmlBufCat(buf, tmp->content);
5400
 
                    else
5401
 
                        xmlBufGetNodeContent(buf, tmp);
5402
 
                    tmp = tmp->next;
5403
 
                }
5404
 
                break;
5405
 
            }
5406
 
        case XML_COMMENT_NODE:
5407
 
        case XML_PI_NODE:
5408
 
            xmlBufCat(buf, cur->content);
5409
 
            break;
5410
 
        case XML_ENTITY_REF_NODE:{
5411
 
                xmlEntityPtr ent;
5412
 
                xmlNodePtr tmp;
5413
 
 
5414
 
                /* lookup entity declaration */
5415
 
                ent = xmlGetDocEntity(cur->doc, cur->name);
5416
 
                if (ent == NULL)
5417
 
                    return(-1);
5418
 
 
5419
 
                /* an entity content can be any "well balanced chunk",
5420
 
                 * i.e. the result of the content [43] production:
5421
 
                 * http://www.w3.org/TR/REC-xml#NT-content
5422
 
                 * -> we iterate through child nodes and recursive call
5423
 
                 * xmlNodeGetContent() which handles all possible node types */
5424
 
                tmp = ent->children;
5425
 
                while (tmp) {
5426
 
                    xmlBufGetNodeContent(buf, tmp);
5427
 
                    tmp = tmp->next;
5428
 
                }
5429
 
                break;
5430
 
            }
5431
 
        case XML_ENTITY_NODE:
5432
 
        case XML_DOCUMENT_TYPE_NODE:
5433
 
        case XML_NOTATION_NODE:
5434
 
        case XML_DTD_NODE:
5435
 
        case XML_XINCLUDE_START:
5436
 
        case XML_XINCLUDE_END:
5437
 
            break;
5438
 
        case XML_DOCUMENT_NODE:
5439
 
#ifdef LIBXML_DOCB_ENABLED
5440
 
        case XML_DOCB_DOCUMENT_NODE:
5441
 
#endif
5442
 
        case XML_HTML_DOCUMENT_NODE:
5443
 
            cur = cur->children;
5444
 
            while (cur!= NULL) {
5445
 
                if ((cur->type == XML_ELEMENT_NODE) ||
5446
 
                    (cur->type == XML_TEXT_NODE) ||
5447
 
                    (cur->type == XML_CDATA_SECTION_NODE)) {
5448
 
                    xmlBufGetNodeContent(buf, cur);
5449
 
                }
5450
 
                cur = cur->next;
5451
 
            }
5452
 
            break;
5453
 
        case XML_NAMESPACE_DECL:
5454
 
            xmlBufCat(buf, ((xmlNsPtr) cur)->href);
5455
 
            break;
5456
 
        case XML_ELEMENT_DECL:
5457
 
        case XML_ATTRIBUTE_DECL:
5458
 
        case XML_ENTITY_DECL:
5459
 
            break;
5460
 
    }
5461
 
    return(0);
5462
 
}
5463
 
 
5464
 
/**
5465
 
 * xmlNodeGetContent:
5466
 
 * @cur:  the node being read
5467
 
 *
5468
 
 * Read the value of a node, this can be either the text carried
5469
 
 * directly by this node if it's a TEXT node or the aggregate string
5470
 
 * of the values carried by this node child's (TEXT and ENTITY_REF).
5471
 
 * Entity references are substituted.
5472
 
 * Returns a new #xmlChar * or NULL if no content is available.
5473
 
 *     It's up to the caller to free the memory with xmlFree().
5474
 
 */
5475
 
xmlChar *
5476
 
xmlNodeGetContent(xmlNodePtr cur)
5477
 
{
5478
 
    if (cur == NULL)
5479
 
        return (NULL);
5480
 
    switch (cur->type) {
5481
 
        case XML_DOCUMENT_FRAG_NODE:
5482
 
        case XML_ELEMENT_NODE:{
5483
 
                xmlBufPtr buf;
5484
 
                xmlChar *ret;
5485
 
 
5486
 
                buf = xmlBufCreateSize(64);
5487
 
                if (buf == NULL)
5488
 
                    return (NULL);
5489
 
                xmlBufGetNodeContent(buf, cur);
5490
 
                ret = xmlBufDetach(buf);
5491
 
                xmlBufFree(buf);
5492
 
                return (ret);
5493
 
            }
5494
 
        case XML_ATTRIBUTE_NODE:
5495
 
            return(xmlGetPropNodeValueInternal((xmlAttrPtr) cur));
5496
 
        case XML_COMMENT_NODE:
5497
 
        case XML_PI_NODE:
5498
 
            if (cur->content != NULL)
5499
 
                return (xmlStrdup(cur->content));
5500
 
            return (NULL);
5501
 
        case XML_ENTITY_REF_NODE:{
5502
 
                xmlEntityPtr ent;
5503
 
                xmlBufPtr buf;
5504
 
                xmlChar *ret;
5505
 
 
5506
 
                /* lookup entity declaration */
5507
 
                ent = xmlGetDocEntity(cur->doc, cur->name);
5508
 
                if (ent == NULL)
5509
 
                    return (NULL);
5510
 
 
5511
 
                buf = xmlBufCreate();
5512
 
                if (buf == NULL)
5513
 
                    return (NULL);
5514
 
 
5515
 
                xmlBufGetNodeContent(buf, cur);
5516
 
 
5517
 
                ret = xmlBufDetach(buf);
5518
 
                xmlBufFree(buf);
5519
 
                return (ret);
5520
 
            }
5521
 
        case XML_ENTITY_NODE:
5522
 
        case XML_DOCUMENT_TYPE_NODE:
5523
 
        case XML_NOTATION_NODE:
5524
 
        case XML_DTD_NODE:
5525
 
        case XML_XINCLUDE_START:
5526
 
        case XML_XINCLUDE_END:
5527
 
            return (NULL);
5528
 
        case XML_DOCUMENT_NODE:
5529
 
#ifdef LIBXML_DOCB_ENABLED
5530
 
        case XML_DOCB_DOCUMENT_NODE:
5531
 
#endif
5532
 
        case XML_HTML_DOCUMENT_NODE: {
5533
 
            xmlBufPtr buf;
5534
 
            xmlChar *ret;
5535
 
 
5536
 
            buf = xmlBufCreate();
5537
 
            if (buf == NULL)
5538
 
                return (NULL);
5539
 
 
5540
 
            xmlBufGetNodeContent(buf, (xmlNodePtr) cur);
5541
 
 
5542
 
            ret = xmlBufDetach(buf);
5543
 
            xmlBufFree(buf);
5544
 
            return (ret);
5545
 
        }
5546
 
        case XML_NAMESPACE_DECL: {
5547
 
            xmlChar *tmp;
5548
 
 
5549
 
            tmp = xmlStrdup(((xmlNsPtr) cur)->href);
5550
 
            return (tmp);
5551
 
        }
5552
 
        case XML_ELEMENT_DECL:
5553
 
            /* TODO !!! */
5554
 
            return (NULL);
5555
 
        case XML_ATTRIBUTE_DECL:
5556
 
            /* TODO !!! */
5557
 
            return (NULL);
5558
 
        case XML_ENTITY_DECL:
5559
 
            /* TODO !!! */
5560
 
            return (NULL);
5561
 
        case XML_CDATA_SECTION_NODE:
5562
 
        case XML_TEXT_NODE:
5563
 
            if (cur->content != NULL)
5564
 
                return (xmlStrdup(cur->content));
5565
 
            return (NULL);
5566
 
    }
5567
 
    return (NULL);
5568
 
}
5569
 
 
5570
 
/**
5571
 
 * xmlNodeSetContent:
5572
 
 * @cur:  the node being modified
5573
 
 * @content:  the new value of the content
5574
 
 *
5575
 
 * Replace the content of a node.
5576
 
 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
5577
 
 *       references, but XML special chars need to be escaped first by using
5578
 
 *       xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
5579
 
 */
5580
 
void
5581
 
xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
5582
 
    if (cur == NULL) {
5583
 
#ifdef DEBUG_TREE
5584
 
        xmlGenericError(xmlGenericErrorContext,
5585
 
                "xmlNodeSetContent : node == NULL\n");
5586
 
#endif
5587
 
        return;
5588
 
    }
5589
 
    switch (cur->type) {
5590
 
        case XML_DOCUMENT_FRAG_NODE:
5591
 
        case XML_ELEMENT_NODE:
5592
 
        case XML_ATTRIBUTE_NODE:
5593
 
            if (cur->children != NULL) xmlFreeNodeList(cur->children);
5594
 
            cur->children = xmlStringGetNodeList(cur->doc, content);
5595
 
            UPDATE_LAST_CHILD_AND_PARENT(cur)
5596
 
            break;
5597
 
        case XML_TEXT_NODE:
5598
 
        case XML_CDATA_SECTION_NODE:
5599
 
        case XML_ENTITY_REF_NODE:
5600
 
        case XML_ENTITY_NODE:
5601
 
        case XML_PI_NODE:
5602
 
        case XML_COMMENT_NODE:
5603
 
            if ((cur->content != NULL) &&
5604
 
                (cur->content != (xmlChar *) &(cur->properties))) {
5605
 
                if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&
5606
 
                    (xmlDictOwns(cur->doc->dict, cur->content))))
5607
 
                    xmlFree(cur->content);
5608
 
            }
5609
 
            if (cur->children != NULL) xmlFreeNodeList(cur->children);
5610
 
            cur->last = cur->children = NULL;
5611
 
            if (content != NULL) {
5612
 
                cur->content = xmlStrdup(content);
5613
 
            } else
5614
 
                cur->content = NULL;
5615
 
            cur->properties = NULL;
5616
 
            cur->nsDef = NULL;
5617
 
            break;
5618
 
        case XML_DOCUMENT_NODE:
5619
 
        case XML_HTML_DOCUMENT_NODE:
5620
 
        case XML_DOCUMENT_TYPE_NODE:
5621
 
        case XML_XINCLUDE_START:
5622
 
        case XML_XINCLUDE_END:
5623
 
#ifdef LIBXML_DOCB_ENABLED
5624
 
        case XML_DOCB_DOCUMENT_NODE:
5625
 
#endif
5626
 
            break;
5627
 
        case XML_NOTATION_NODE:
5628
 
            break;
5629
 
        case XML_DTD_NODE:
5630
 
            break;
5631
 
        case XML_NAMESPACE_DECL:
5632
 
            break;
5633
 
        case XML_ELEMENT_DECL:
5634
 
            /* TODO !!! */
5635
 
            break;
5636
 
        case XML_ATTRIBUTE_DECL:
5637
 
            /* TODO !!! */
5638
 
            break;
5639
 
        case XML_ENTITY_DECL:
5640
 
            /* TODO !!! */
5641
 
            break;
5642
 
    }
5643
 
}
5644
 
 
5645
 
#ifdef LIBXML_TREE_ENABLED
5646
 
/**
5647
 
 * xmlNodeSetContentLen:
5648
 
 * @cur:  the node being modified
5649
 
 * @content:  the new value of the content
5650
 
 * @len:  the size of @content
5651
 
 *
5652
 
 * Replace the content of a node.
5653
 
 * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity
5654
 
 *       references, but XML special chars need to be escaped first by using
5655
 
 *       xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().
5656
 
 */
5657
 
void
5658
 
xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
5659
 
    if (cur == NULL) {
5660
 
#ifdef DEBUG_TREE
5661
 
        xmlGenericError(xmlGenericErrorContext,
5662
 
                "xmlNodeSetContentLen : node == NULL\n");
5663
 
#endif
5664
 
        return;
5665
 
    }
5666
 
    switch (cur->type) {
5667
 
        case XML_DOCUMENT_FRAG_NODE:
5668
 
        case XML_ELEMENT_NODE:
5669
 
        case XML_ATTRIBUTE_NODE:
5670
 
            if (cur->children != NULL) xmlFreeNodeList(cur->children);
5671
 
            cur->children = xmlStringLenGetNodeList(cur->doc, content, len);
5672
 
            UPDATE_LAST_CHILD_AND_PARENT(cur)
5673
 
            break;
5674
 
        case XML_TEXT_NODE:
5675
 
        case XML_CDATA_SECTION_NODE:
5676
 
        case XML_ENTITY_REF_NODE:
5677
 
        case XML_ENTITY_NODE:
5678
 
        case XML_PI_NODE:
5679
 
        case XML_COMMENT_NODE:
5680
 
        case XML_NOTATION_NODE:
5681
 
            if ((cur->content != NULL) &&
5682
 
                (cur->content != (xmlChar *) &(cur->properties))) {
5683
 
                if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&
5684
 
                    (xmlDictOwns(cur->doc->dict, cur->content))))
5685
 
                    xmlFree(cur->content);
5686
 
            }
5687
 
            if (cur->children != NULL) xmlFreeNodeList(cur->children);
5688
 
            cur->children = cur->last = NULL;
5689
 
            if (content != NULL) {
5690
 
                cur->content = xmlStrndup(content, len);
5691
 
            } else
5692
 
                cur->content = NULL;
5693
 
            cur->properties = NULL;
5694
 
            cur->nsDef = NULL;
5695
 
            break;
5696
 
        case XML_DOCUMENT_NODE:
5697
 
        case XML_DTD_NODE:
5698
 
        case XML_HTML_DOCUMENT_NODE:
5699
 
        case XML_DOCUMENT_TYPE_NODE:
5700
 
        case XML_NAMESPACE_DECL:
5701
 
        case XML_XINCLUDE_START:
5702
 
        case XML_XINCLUDE_END:
5703
 
#ifdef LIBXML_DOCB_ENABLED
5704
 
        case XML_DOCB_DOCUMENT_NODE:
5705
 
#endif
5706
 
            break;
5707
 
        case XML_ELEMENT_DECL:
5708
 
            /* TODO !!! */
5709
 
            break;
5710
 
        case XML_ATTRIBUTE_DECL:
5711
 
            /* TODO !!! */
5712
 
            break;
5713
 
        case XML_ENTITY_DECL:
5714
 
            /* TODO !!! */
5715
 
            break;
5716
 
    }
5717
 
}
5718
 
#endif /* LIBXML_TREE_ENABLED */
5719
 
 
5720
 
/**
5721
 
 * xmlNodeAddContentLen:
5722
 
 * @cur:  the node being modified
5723
 
 * @content:  extra content
5724
 
 * @len:  the size of @content
5725
 
 *
5726
 
 * Append the extra substring to the node content.
5727
 
 * NOTE: In contrast to xmlNodeSetContentLen(), @content is supposed to be
5728
 
 *       raw text, so unescaped XML special chars are allowed, entity
5729
 
 *       references are not supported.
5730
 
 */
5731
 
void
5732
 
xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
5733
 
    if (cur == NULL) {
5734
 
#ifdef DEBUG_TREE
5735
 
        xmlGenericError(xmlGenericErrorContext,
5736
 
                "xmlNodeAddContentLen : node == NULL\n");
5737
 
#endif
5738
 
        return;
5739
 
    }
5740
 
    if (len <= 0) return;
5741
 
    switch (cur->type) {
5742
 
        case XML_DOCUMENT_FRAG_NODE:
5743
 
        case XML_ELEMENT_NODE: {
5744
 
            xmlNodePtr last, newNode, tmp;
5745
 
 
5746
 
            last = cur->last;
5747
 
            newNode = xmlNewTextLen(content, len);
5748
 
            if (newNode != NULL) {
5749
 
                tmp = xmlAddChild(cur, newNode);
5750
 
                if (tmp != newNode)
5751
 
                    return;
5752
 
                if ((last != NULL) && (last->next == newNode)) {
5753
 
                    xmlTextMerge(last, newNode);
5754
 
                }
5755
 
            }
5756
 
            break;
5757
 
        }
5758
 
        case XML_ATTRIBUTE_NODE:
5759
 
            break;
5760
 
        case XML_TEXT_NODE:
5761
 
        case XML_CDATA_SECTION_NODE:
5762
 
        case XML_ENTITY_REF_NODE:
5763
 
        case XML_ENTITY_NODE:
5764
 
        case XML_PI_NODE:
5765
 
        case XML_COMMENT_NODE:
5766
 
        case XML_NOTATION_NODE:
5767
 
            if (content != NULL) {
5768
 
                if ((cur->content == (xmlChar *) &(cur->properties)) ||
5769
 
                    ((cur->doc != NULL) && (cur->doc->dict != NULL) &&
5770
 
                            xmlDictOwns(cur->doc->dict, cur->content))) {
5771
 
                    cur->content = xmlStrncatNew(cur->content, content, len);
5772
 
                    cur->properties = NULL;
5773
 
                    cur->nsDef = NULL;
5774
 
                    break;
5775
 
                }
5776
 
                cur->content = xmlStrncat(cur->content, content, len);
5777
 
            }
5778
 
        case XML_DOCUMENT_NODE:
5779
 
        case XML_DTD_NODE:
5780
 
        case XML_HTML_DOCUMENT_NODE:
5781
 
        case XML_DOCUMENT_TYPE_NODE:
5782
 
        case XML_NAMESPACE_DECL:
5783
 
        case XML_XINCLUDE_START:
5784
 
        case XML_XINCLUDE_END:
5785
 
#ifdef LIBXML_DOCB_ENABLED
5786
 
        case XML_DOCB_DOCUMENT_NODE:
5787
 
#endif
5788
 
            break;
5789
 
        case XML_ELEMENT_DECL:
5790
 
        case XML_ATTRIBUTE_DECL:
5791
 
        case XML_ENTITY_DECL:
5792
 
            break;
5793
 
    }
5794
 
}
5795
 
 
5796
 
/**
5797
 
 * xmlNodeAddContent:
5798
 
 * @cur:  the node being modified
5799
 
 * @content:  extra content
5800
 
 *
5801
 
 * Append the extra substring to the node content.
5802
 
 * NOTE: In contrast to xmlNodeSetContent(), @content is supposed to be
5803
 
 *       raw text, so unescaped XML special chars are allowed, entity
5804
 
 *       references are not supported.
5805
 
 */
5806
 
void
5807
 
xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
5808
 
    int len;
5809
 
 
5810
 
    if (cur == NULL) {
5811
 
#ifdef DEBUG_TREE
5812
 
        xmlGenericError(xmlGenericErrorContext,
5813
 
                "xmlNodeAddContent : node == NULL\n");
5814
 
#endif
5815
 
        return;
5816
 
    }
5817
 
    if (content == NULL) return;
5818
 
    len = xmlStrlen(content);
5819
 
    xmlNodeAddContentLen(cur, content, len);
5820
 
}
5821
 
 
5822
 
/**
5823
 
 * xmlTextMerge:
5824
 
 * @first:  the first text node
5825
 
 * @second:  the second text node being merged
5826
 
 *
5827
 
 * Merge two text nodes into one
5828
 
 * Returns the first text node augmented
5829
 
 */
5830
 
xmlNodePtr
5831
 
xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
5832
 
    if (first == NULL) return(second);
5833
 
    if (second == NULL) return(first);
5834
 
    if (first->type != XML_TEXT_NODE) return(first);
5835
 
    if (second->type != XML_TEXT_NODE) return(first);
5836
 
    if (second->name != first->name)
5837
 
        return(first);
5838
 
    xmlNodeAddContent(first, second->content);
5839
 
    xmlUnlinkNode(second);
5840
 
    xmlFreeNode(second);
5841
 
    return(first);
5842
 
}
5843
 
 
5844
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
5845
 
/**
5846
 
 * xmlGetNsList:
5847
 
 * @doc:  the document
5848
 
 * @node:  the current node
5849
 
 *
5850
 
 * Search all the namespace applying to a given element.
5851
 
 * Returns an NULL terminated array of all the #xmlNsPtr found
5852
 
 *         that need to be freed by the caller or NULL if no
5853
 
 *         namespace if defined
5854
 
 */
5855
 
xmlNsPtr *
5856
 
xmlGetNsList(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node)
5857
 
{
5858
 
    xmlNsPtr cur;
5859
 
    xmlNsPtr *ret = NULL;
5860
 
    int nbns = 0;
5861
 
    int maxns = 10;
5862
 
    int i;
5863
 
 
5864
 
    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
5865
 
        return(NULL);
5866
 
 
5867
 
    while (node != NULL) {
5868
 
        if (node->type == XML_ELEMENT_NODE) {
5869
 
            cur = node->nsDef;
5870
 
            while (cur != NULL) {
5871
 
                if (ret == NULL) {
5872
 
                    ret =
5873
 
                        (xmlNsPtr *) xmlMalloc((maxns + 1) *
5874
 
                                               sizeof(xmlNsPtr));
5875
 
                    if (ret == NULL) {
5876
 
                        xmlTreeErrMemory("getting namespace list");
5877
 
                        return (NULL);
5878
 
                    }
5879
 
                    ret[nbns] = NULL;
5880
 
                }
5881
 
                for (i = 0; i < nbns; i++) {
5882
 
                    if ((cur->prefix == ret[i]->prefix) ||
5883
 
                        (xmlStrEqual(cur->prefix, ret[i]->prefix)))
5884
 
                        break;
5885
 
                }
5886
 
                if (i >= nbns) {
5887
 
                    if (nbns >= maxns) {
5888
 
                        maxns *= 2;
5889
 
                        ret = (xmlNsPtr *) xmlRealloc(ret,
5890
 
                                                      (maxns +
5891
 
                                                       1) *
5892
 
                                                      sizeof(xmlNsPtr));
5893
 
                        if (ret == NULL) {
5894
 
                            xmlTreeErrMemory("getting namespace list");
5895
 
                            return (NULL);
5896
 
                        }
5897
 
                    }
5898
 
                    ret[nbns++] = cur;
5899
 
                    ret[nbns] = NULL;
5900
 
                }
5901
 
 
5902
 
                cur = cur->next;
5903
 
            }
5904
 
        }
5905
 
        node = node->parent;
5906
 
    }
5907
 
    return (ret);
5908
 
}
5909
 
#endif /* LIBXML_TREE_ENABLED */
5910
 
 
5911
 
/*
5912
 
* xmlTreeEnsureXMLDecl:
5913
 
* @doc: the doc
5914
 
*
5915
 
* Ensures that there is an XML namespace declaration on the doc.
5916
 
*
5917
 
* Returns the XML ns-struct or NULL on API and internal errors.
5918
 
*/
5919
 
static xmlNsPtr
5920
 
xmlTreeEnsureXMLDecl(xmlDocPtr doc)
5921
 
{
5922
 
    if (doc == NULL)
5923
 
        return (NULL);
5924
 
    if (doc->oldNs != NULL)
5925
 
        return (doc->oldNs);
5926
 
    {
5927
 
        xmlNsPtr ns;
5928
 
        ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
5929
 
        if (ns == NULL) {
5930
 
            xmlTreeErrMemory(
5931
 
                "allocating the XML namespace");
5932
 
            return (NULL);
5933
 
        }
5934
 
        memset(ns, 0, sizeof(xmlNs));
5935
 
        ns->type = XML_LOCAL_NAMESPACE;
5936
 
        ns->href = xmlStrdup(XML_XML_NAMESPACE);
5937
 
        ns->prefix = xmlStrdup((const xmlChar *)"xml");
5938
 
        doc->oldNs = ns;
5939
 
        return (ns);
5940
 
    }
5941
 
}
5942
 
 
5943
 
/**
5944
 
 * xmlSearchNs:
5945
 
 * @doc:  the document
5946
 
 * @node:  the current node
5947
 
 * @nameSpace:  the namespace prefix
5948
 
 *
5949
 
 * Search a Ns registered under a given name space for a document.
5950
 
 * recurse on the parents until it finds the defined namespace
5951
 
 * or return NULL otherwise.
5952
 
 * @nameSpace can be NULL, this is a search for the default namespace.
5953
 
 * We don't allow to cross entities boundaries. If you don't declare
5954
 
 * the namespace within those you will be in troubles !!! A warning
5955
 
 * is generated to cover this case.
5956
 
 *
5957
 
 * Returns the namespace pointer or NULL.
5958
 
 */
5959
 
xmlNsPtr
5960
 
xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
5961
 
 
5962
 
    xmlNsPtr cur;
5963
 
    xmlNodePtr orig = node;
5964
 
 
5965
 
    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) return(NULL);
5966
 
    if ((nameSpace != NULL) &&
5967
 
        (xmlStrEqual(nameSpace, (const xmlChar *)"xml"))) {
5968
 
        if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) {
5969
 
            /*
5970
 
             * The XML-1.0 namespace is normally held on the root
5971
 
             * element. In this case exceptionally create it on the
5972
 
             * node element.
5973
 
             */
5974
 
            cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
5975
 
            if (cur == NULL) {
5976
 
                xmlTreeErrMemory("searching namespace");
5977
 
                return(NULL);
5978
 
            }
5979
 
            memset(cur, 0, sizeof(xmlNs));
5980
 
            cur->type = XML_LOCAL_NAMESPACE;
5981
 
            cur->href = xmlStrdup(XML_XML_NAMESPACE);
5982
 
            cur->prefix = xmlStrdup((const xmlChar *)"xml");
5983
 
            cur->next = node->nsDef;
5984
 
            node->nsDef = cur;
5985
 
            return(cur);
5986
 
        }
5987
 
        if (doc == NULL) {
5988
 
            doc = node->doc;
5989
 
            if (doc == NULL)
5990
 
                return(NULL);
5991
 
        }
5992
 
        /*
5993
 
        * Return the XML namespace declaration held by the doc.
5994
 
        */
5995
 
        if (doc->oldNs == NULL)
5996
 
            return(xmlTreeEnsureXMLDecl(doc));
5997
 
        else
5998
 
            return(doc->oldNs);
5999
 
    }
6000
 
    while (node != NULL) {
6001
 
        if ((node->type == XML_ENTITY_REF_NODE) ||
6002
 
            (node->type == XML_ENTITY_NODE) ||
6003
 
            (node->type == XML_ENTITY_DECL))
6004
 
            return(NULL);
6005
 
        if (node->type == XML_ELEMENT_NODE) {
6006
 
            cur = node->nsDef;
6007
 
            while (cur != NULL) {
6008
 
                if ((cur->prefix == NULL) && (nameSpace == NULL) &&
6009
 
                    (cur->href != NULL))
6010
 
                    return(cur);
6011
 
                if ((cur->prefix != NULL) && (nameSpace != NULL) &&
6012
 
                    (cur->href != NULL) &&
6013
 
                    (xmlStrEqual(cur->prefix, nameSpace)))
6014
 
                    return(cur);
6015
 
                cur = cur->next;
6016
 
            }
6017
 
            if (orig != node) {
6018
 
                cur = node->ns;
6019
 
                if (cur != NULL) {
6020
 
                    if ((cur->prefix == NULL) && (nameSpace == NULL) &&
6021
 
                        (cur->href != NULL))
6022
 
                        return(cur);
6023
 
                    if ((cur->prefix != NULL) && (nameSpace != NULL) &&
6024
 
                        (cur->href != NULL) &&
6025
 
                        (xmlStrEqual(cur->prefix, nameSpace)))
6026
 
                        return(cur);
6027
 
                }
6028
 
            }
6029
 
        }
6030
 
        node = node->parent;
6031
 
    }
6032
 
    return(NULL);
6033
 
}
6034
 
 
6035
 
/**
6036
 
 * xmlNsInScope:
6037
 
 * @doc:  the document
6038
 
 * @node:  the current node
6039
 
 * @ancestor:  the ancestor carrying the namespace
6040
 
 * @prefix:  the namespace prefix
6041
 
 *
6042
 
 * Verify that the given namespace held on @ancestor is still in scope
6043
 
 * on node.
6044
 
 *
6045
 
 * Returns 1 if true, 0 if false and -1 in case of error.
6046
 
 */
6047
 
static int
6048
 
xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node,
6049
 
             xmlNodePtr ancestor, const xmlChar * prefix)
6050
 
{
6051
 
    xmlNsPtr tst;
6052
 
 
6053
 
    while ((node != NULL) && (node != ancestor)) {
6054
 
        if ((node->type == XML_ENTITY_REF_NODE) ||
6055
 
            (node->type == XML_ENTITY_NODE) ||
6056
 
            (node->type == XML_ENTITY_DECL))
6057
 
            return (-1);
6058
 
        if (node->type == XML_ELEMENT_NODE) {
6059
 
            tst = node->nsDef;
6060
 
            while (tst != NULL) {
6061
 
                if ((tst->prefix == NULL)
6062
 
                    && (prefix == NULL))
6063
 
                    return (0);
6064
 
                if ((tst->prefix != NULL)
6065
 
                    && (prefix != NULL)
6066
 
                    && (xmlStrEqual(tst->prefix, prefix)))
6067
 
                    return (0);
6068
 
                tst = tst->next;
6069
 
            }
6070
 
        }
6071
 
        node = node->parent;
6072
 
    }
6073
 
    if (node != ancestor)
6074
 
        return (-1);
6075
 
    return (1);
6076
 
}
6077
 
 
6078
 
/**
6079
 
 * xmlSearchNsByHref:
6080
 
 * @doc:  the document
6081
 
 * @node:  the current node
6082
 
 * @href:  the namespace value
6083
 
 *
6084
 
 * Search a Ns aliasing a given URI. Recurse on the parents until it finds
6085
 
 * the defined namespace or return NULL otherwise.
6086
 
 * Returns the namespace pointer or NULL.
6087
 
 */
6088
 
xmlNsPtr
6089
 
xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href)
6090
 
{
6091
 
    xmlNsPtr cur;
6092
 
    xmlNodePtr orig = node;
6093
 
    int is_attr;
6094
 
 
6095
 
    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) || (href == NULL))
6096
 
        return (NULL);
6097
 
    if (xmlStrEqual(href, XML_XML_NAMESPACE)) {
6098
 
        /*
6099
 
         * Only the document can hold the XML spec namespace.
6100
 
         */
6101
 
        if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) {
6102
 
            /*
6103
 
             * The XML-1.0 namespace is normally held on the root
6104
 
             * element. In this case exceptionally create it on the
6105
 
             * node element.
6106
 
             */
6107
 
            cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
6108
 
            if (cur == NULL) {
6109
 
                xmlTreeErrMemory("searching namespace");
6110
 
                return (NULL);
6111
 
            }
6112
 
            memset(cur, 0, sizeof(xmlNs));
6113
 
            cur->type = XML_LOCAL_NAMESPACE;
6114
 
            cur->href = xmlStrdup(XML_XML_NAMESPACE);
6115
 
            cur->prefix = xmlStrdup((const xmlChar *) "xml");
6116
 
            cur->next = node->nsDef;
6117
 
            node->nsDef = cur;
6118
 
            return (cur);
6119
 
        }
6120
 
        if (doc == NULL) {
6121
 
            doc = node->doc;
6122
 
            if (doc == NULL)
6123
 
                return(NULL);
6124
 
        }
6125
 
        /*
6126
 
        * Return the XML namespace declaration held by the doc.
6127
 
        */
6128
 
        if (doc->oldNs == NULL)
6129
 
            return(xmlTreeEnsureXMLDecl(doc));
6130
 
        else
6131
 
            return(doc->oldNs);
6132
 
    }
6133
 
    is_attr = (node->type == XML_ATTRIBUTE_NODE);
6134
 
    while (node != NULL) {
6135
 
        if ((node->type == XML_ENTITY_REF_NODE) ||
6136
 
            (node->type == XML_ENTITY_NODE) ||
6137
 
            (node->type == XML_ENTITY_DECL))
6138
 
            return (NULL);
6139
 
        if (node->type == XML_ELEMENT_NODE) {
6140
 
            cur = node->nsDef;
6141
 
            while (cur != NULL) {
6142
 
                if ((cur->href != NULL) && (href != NULL) &&
6143
 
                    (xmlStrEqual(cur->href, href))) {
6144
 
                    if (((!is_attr) || (cur->prefix != NULL)) &&
6145
 
                        (xmlNsInScope(doc, orig, node, cur->prefix) == 1))
6146
 
                        return (cur);
6147
 
                }
6148
 
                cur = cur->next;
6149
 
            }
6150
 
            if (orig != node) {
6151
 
                cur = node->ns;
6152
 
                if (cur != NULL) {
6153
 
                    if ((cur->href != NULL) && (href != NULL) &&
6154
 
                        (xmlStrEqual(cur->href, href))) {
6155
 
                        if (((!is_attr) || (cur->prefix != NULL)) &&
6156
 
                            (xmlNsInScope(doc, orig, node, cur->prefix) == 1))
6157
 
                            return (cur);
6158
 
                    }
6159
 
                }
6160
 
            }
6161
 
        }
6162
 
        node = node->parent;
6163
 
    }
6164
 
    return (NULL);
6165
 
}
6166
 
 
6167
 
/**
6168
 
 * xmlNewReconciliedNs:
6169
 
 * @doc:  the document
6170
 
 * @tree:  a node expected to hold the new namespace
6171
 
 * @ns:  the original namespace
6172
 
 *
6173
 
 * This function tries to locate a namespace definition in a tree
6174
 
 * ancestors, or create a new namespace definition node similar to
6175
 
 * @ns trying to reuse the same prefix. However if the given prefix is
6176
 
 * null (default namespace) or reused within the subtree defined by
6177
 
 * @tree or on one of its ancestors then a new prefix is generated.
6178
 
 * Returns the (new) namespace definition or NULL in case of error
6179
 
 */
6180
 
static xmlNsPtr
6181
 
xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
6182
 
    xmlNsPtr def;
6183
 
    xmlChar prefix[50];
6184
 
    int counter = 1;
6185
 
 
6186
 
    if ((tree == NULL) || (tree->type != XML_ELEMENT_NODE)) {
6187
 
#ifdef DEBUG_TREE
6188
 
        xmlGenericError(xmlGenericErrorContext,
6189
 
                "xmlNewReconciliedNs : tree == NULL\n");
6190
 
#endif
6191
 
        return(NULL);
6192
 
    }
6193
 
    if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) {
6194
 
#ifdef DEBUG_TREE
6195
 
        xmlGenericError(xmlGenericErrorContext,
6196
 
                "xmlNewReconciliedNs : ns == NULL\n");
6197
 
#endif
6198
 
        return(NULL);
6199
 
    }
6200
 
    /*
6201
 
     * Search an existing namespace definition inherited.
6202
 
     */
6203
 
    def = xmlSearchNsByHref(doc, tree, ns->href);
6204
 
    if (def != NULL)
6205
 
        return(def);
6206
 
 
6207
 
    /*
6208
 
     * Find a close prefix which is not already in use.
6209
 
     * Let's strip namespace prefixes longer than 20 chars !
6210
 
     */
6211
 
    if (ns->prefix == NULL)
6212
 
        snprintf((char *) prefix, sizeof(prefix), "default");
6213
 
    else
6214
 
        snprintf((char *) prefix, sizeof(prefix), "%.20s", (char *)ns->prefix);
6215
 
 
6216
 
    def = xmlSearchNs(doc, tree, prefix);
6217
 
    while (def != NULL) {
6218
 
        if (counter > 1000) return(NULL);
6219
 
        if (ns->prefix == NULL)
6220
 
            snprintf((char *) prefix, sizeof(prefix), "default%d", counter++);
6221
 
        else
6222
 
            snprintf((char *) prefix, sizeof(prefix), "%.20s%d",
6223
 
                (char *)ns->prefix, counter++);
6224
 
        def = xmlSearchNs(doc, tree, prefix);
6225
 
    }
6226
 
 
6227
 
    /*
6228
 
     * OK, now we are ready to create a new one.
6229
 
     */
6230
 
    def = xmlNewNs(tree, ns->href, prefix);
6231
 
    return(def);
6232
 
}
6233
 
 
6234
 
#ifdef LIBXML_TREE_ENABLED
6235
 
/**
6236
 
 * xmlReconciliateNs:
6237
 
 * @doc:  the document
6238
 
 * @tree:  a node defining the subtree to reconciliate
6239
 
 *
6240
 
 * This function checks that all the namespaces declared within the given
6241
 
 * tree are properly declared. This is needed for example after Copy or Cut
6242
 
 * and then paste operations. The subtree may still hold pointers to
6243
 
 * namespace declarations outside the subtree or invalid/masked. As much
6244
 
 * as possible the function try to reuse the existing namespaces found in
6245
 
 * the new environment. If not possible the new namespaces are redeclared
6246
 
 * on @tree at the top of the given subtree.
6247
 
 * Returns the number of namespace declarations created or -1 in case of error.
6248
 
 */
6249
 
int
6250
 
xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
6251
 
    xmlNsPtr *oldNs = NULL;
6252
 
    xmlNsPtr *newNs = NULL;
6253
 
    int sizeCache = 0;
6254
 
    int nbCache = 0;
6255
 
 
6256
 
    xmlNsPtr n;
6257
 
    xmlNodePtr node = tree;
6258
 
    xmlAttrPtr attr;
6259
 
    int ret = 0, i;
6260
 
 
6261
 
    if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) return(-1);
6262
 
    if ((doc == NULL) || (doc->type != XML_DOCUMENT_NODE)) return(-1);
6263
 
    if (node->doc != doc) return(-1);
6264
 
    while (node != NULL) {
6265
 
        /*
6266
 
         * Reconciliate the node namespace
6267
 
         */
6268
 
        if (node->ns != NULL) {
6269
 
            /*
6270
 
             * initialize the cache if needed
6271
 
             */
6272
 
            if (sizeCache == 0) {
6273
 
                sizeCache = 10;
6274
 
                oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
6275
 
                                               sizeof(xmlNsPtr));
6276
 
                if (oldNs == NULL) {
6277
 
                    xmlTreeErrMemory("fixing namespaces");
6278
 
                    return(-1);
6279
 
                }
6280
 
                newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
6281
 
                                               sizeof(xmlNsPtr));
6282
 
                if (newNs == NULL) {
6283
 
                    xmlTreeErrMemory("fixing namespaces");
6284
 
                    xmlFree(oldNs);
6285
 
                    return(-1);
6286
 
                }
6287
 
            }
6288
 
            for (i = 0;i < nbCache;i++) {
6289
 
                if (oldNs[i] == node->ns) {
6290
 
                    node->ns = newNs[i];
6291
 
                    break;
6292
 
                }
6293
 
            }
6294
 
            if (i == nbCache) {
6295
 
                /*
6296
 
                 * OK we need to recreate a new namespace definition
6297
 
                 */
6298
 
                n = xmlNewReconciliedNs(doc, tree, node->ns);
6299
 
                if (n != NULL) { /* :-( what if else ??? */
6300
 
                    /*
6301
 
                     * check if we need to grow the cache buffers.
6302
 
                     */
6303
 
                    if (sizeCache <= nbCache) {
6304
 
                        sizeCache *= 2;
6305
 
                        oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
6306
 
                                                       sizeof(xmlNsPtr));
6307
 
                        if (oldNs == NULL) {
6308
 
                            xmlTreeErrMemory("fixing namespaces");
6309
 
                            xmlFree(newNs);
6310
 
                            return(-1);
6311
 
                        }
6312
 
                        newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
6313
 
                                                       sizeof(xmlNsPtr));
6314
 
                        if (newNs == NULL) {
6315
 
                            xmlTreeErrMemory("fixing namespaces");
6316
 
                            xmlFree(oldNs);
6317
 
                            return(-1);
6318
 
                        }
6319
 
                    }
6320
 
                    newNs[nbCache] = n;
6321
 
                    oldNs[nbCache++] = node->ns;
6322
 
                    node->ns = n;
6323
 
                }
6324
 
            }
6325
 
        }
6326
 
        /*
6327
 
         * now check for namespace hold by attributes on the node.
6328
 
         */
6329
 
        if (node->type == XML_ELEMENT_NODE) {
6330
 
            attr = node->properties;
6331
 
            while (attr != NULL) {
6332
 
                if (attr->ns != NULL) {
6333
 
                    /*
6334
 
                     * initialize the cache if needed
6335
 
                     */
6336
 
                    if (sizeCache == 0) {
6337
 
                        sizeCache = 10;
6338
 
                        oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
6339
 
                                                       sizeof(xmlNsPtr));
6340
 
                        if (oldNs == NULL) {
6341
 
                            xmlTreeErrMemory("fixing namespaces");
6342
 
                            return(-1);
6343
 
                        }
6344
 
                        newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
6345
 
                                                       sizeof(xmlNsPtr));
6346
 
                        if (newNs == NULL) {
6347
 
                            xmlTreeErrMemory("fixing namespaces");
6348
 
                            xmlFree(oldNs);
6349
 
                            return(-1);
6350
 
                        }
6351
 
                    }
6352
 
                    for (i = 0;i < nbCache;i++) {
6353
 
                        if (oldNs[i] == attr->ns) {
6354
 
                            attr->ns = newNs[i];
6355
 
                            break;
6356
 
                        }
6357
 
                    }
6358
 
                    if (i == nbCache) {
6359
 
                        /*
6360
 
                         * OK we need to recreate a new namespace definition
6361
 
                         */
6362
 
                        n = xmlNewReconciliedNs(doc, tree, attr->ns);
6363
 
                        if (n != NULL) { /* :-( what if else ??? */
6364
 
                            /*
6365
 
                             * check if we need to grow the cache buffers.
6366
 
                             */
6367
 
                            if (sizeCache <= nbCache) {
6368
 
                                sizeCache *= 2;
6369
 
                                oldNs = (xmlNsPtr *) xmlRealloc(oldNs,
6370
 
                                           sizeCache * sizeof(xmlNsPtr));
6371
 
                                if (oldNs == NULL) {
6372
 
                                    xmlTreeErrMemory("fixing namespaces");
6373
 
                                    xmlFree(newNs);
6374
 
                                    return(-1);
6375
 
                                }
6376
 
                                newNs = (xmlNsPtr *) xmlRealloc(newNs,
6377
 
                                           sizeCache * sizeof(xmlNsPtr));
6378
 
                                if (newNs == NULL) {
6379
 
                                    xmlTreeErrMemory("fixing namespaces");
6380
 
                                    xmlFree(oldNs);
6381
 
                                    return(-1);
6382
 
                                }
6383
 
                            }
6384
 
                            newNs[nbCache] = n;
6385
 
                            oldNs[nbCache++] = attr->ns;
6386
 
                            attr->ns = n;
6387
 
                        }
6388
 
                    }
6389
 
                }
6390
 
                attr = attr->next;
6391
 
            }
6392
 
        }
6393
 
 
6394
 
        /*
6395
 
         * Browse the full subtree, deep first
6396
 
         */
6397
 
        if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
6398
 
            /* deep first */
6399
 
            node = node->children;
6400
 
        } else if ((node != tree) && (node->next != NULL)) {
6401
 
            /* then siblings */
6402
 
            node = node->next;
6403
 
        } else if (node != tree) {
6404
 
            /* go up to parents->next if needed */
6405
 
            while (node != tree) {
6406
 
                if (node->parent != NULL)
6407
 
                    node = node->parent;
6408
 
                if ((node != tree) && (node->next != NULL)) {
6409
 
                    node = node->next;
6410
 
                    break;
6411
 
                }
6412
 
                if (node->parent == NULL) {
6413
 
                    node = NULL;
6414
 
                    break;
6415
 
                }
6416
 
            }
6417
 
            /* exit condition */
6418
 
            if (node == tree)
6419
 
                node = NULL;
6420
 
        } else
6421
 
            break;
6422
 
    }
6423
 
    if (oldNs != NULL)
6424
 
        xmlFree(oldNs);
6425
 
    if (newNs != NULL)
6426
 
        xmlFree(newNs);
6427
 
    return(ret);
6428
 
}
6429
 
#endif /* LIBXML_TREE_ENABLED */
6430
 
 
6431
 
static xmlAttrPtr
6432
 
xmlGetPropNodeInternal(xmlNodePtr node, const xmlChar *name,
6433
 
                       const xmlChar *nsName, int useDTD)
6434
 
{
6435
 
    xmlAttrPtr prop;
6436
 
 
6437
 
    if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
6438
 
        return(NULL);
6439
 
 
6440
 
    if (node->properties != NULL) {
6441
 
        prop = node->properties;
6442
 
        if (nsName == NULL) {
6443
 
            /*
6444
 
            * We want the attr to be in no namespace.
6445
 
            */
6446
 
            do {
6447
 
                if ((prop->ns == NULL) && xmlStrEqual(prop->name, name)) {
6448
 
                    return(prop);
6449
 
                }
6450
 
                prop = prop->next;
6451
 
            } while (prop != NULL);
6452
 
        } else {
6453
 
            /*
6454
 
            * We want the attr to be in the specified namespace.
6455
 
            */
6456
 
            do {
6457
 
                if ((prop->ns != NULL) && xmlStrEqual(prop->name, name) &&
6458
 
                    ((prop->ns->href == nsName) ||
6459
 
                     xmlStrEqual(prop->ns->href, nsName)))
6460
 
                {
6461
 
                    return(prop);
6462
 
                }
6463
 
                prop = prop->next;
6464
 
            } while (prop != NULL);
6465
 
        }
6466
 
    }
6467
 
 
6468
 
#ifdef LIBXML_TREE_ENABLED
6469
 
    if (! useDTD)
6470
 
        return(NULL);
6471
 
    /*
6472
 
     * Check if there is a default/fixed attribute declaration in
6473
 
     * the internal or external subset.
6474
 
     */
6475
 
    if ((node->doc != NULL) && (node->doc->intSubset != NULL)) {
6476
 
        xmlDocPtr doc = node->doc;
6477
 
        xmlAttributePtr attrDecl = NULL;
6478
 
        xmlChar *elemQName, *tmpstr = NULL;
6479
 
 
6480
 
        /*
6481
 
        * We need the QName of the element for the DTD-lookup.
6482
 
        */
6483
 
        if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
6484
 
            tmpstr = xmlStrdup(node->ns->prefix);
6485
 
            tmpstr = xmlStrcat(tmpstr, BAD_CAST ":");
6486
 
            tmpstr = xmlStrcat(tmpstr, node->name);
6487
 
            if (tmpstr == NULL)
6488
 
                return(NULL);
6489
 
            elemQName = tmpstr;
6490
 
        } else
6491
 
            elemQName = (xmlChar *) node->name;
6492
 
        if (nsName == NULL) {
6493
 
            /*
6494
 
            * The common and nice case: Attr in no namespace.
6495
 
            */
6496
 
            attrDecl = xmlGetDtdQAttrDesc(doc->intSubset,
6497
 
                elemQName, name, NULL);
6498
 
            if ((attrDecl == NULL) && (doc->extSubset != NULL)) {
6499
 
                attrDecl = xmlGetDtdQAttrDesc(doc->extSubset,
6500
 
                    elemQName, name, NULL);
6501
 
            }
6502
 
        } else {
6503
 
            xmlNsPtr *nsList, *cur;
6504
 
 
6505
 
            /*
6506
 
            * The ugly case: Search using the prefixes of in-scope
6507
 
            * ns-decls corresponding to @nsName.
6508
 
            */
6509
 
            nsList = xmlGetNsList(node->doc, node);
6510
 
            if (nsList == NULL) {
6511
 
                if (tmpstr != NULL)
6512
 
                    xmlFree(tmpstr);
6513
 
                return(NULL);
6514
 
            }
6515
 
            cur = nsList;
6516
 
            while (*cur != NULL) {
6517
 
                if (xmlStrEqual((*cur)->href, nsName)) {
6518
 
                    attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elemQName,
6519
 
                        name, (*cur)->prefix);
6520
 
                    if (attrDecl)
6521
 
                        break;
6522
 
                    if (doc->extSubset != NULL) {
6523
 
                        attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elemQName,
6524
 
                            name, (*cur)->prefix);
6525
 
                        if (attrDecl)
6526
 
                            break;
6527
 
                    }
6528
 
                }
6529
 
                cur++;
6530
 
            }
6531
 
            xmlFree(nsList);
6532
 
        }
6533
 
        if (tmpstr != NULL)
6534
 
            xmlFree(tmpstr);
6535
 
        /*
6536
 
        * Only default/fixed attrs are relevant.
6537
 
        */
6538
 
        if ((attrDecl != NULL) && (attrDecl->defaultValue != NULL))
6539
 
            return((xmlAttrPtr) attrDecl);
6540
 
    }
6541
 
#endif /* LIBXML_TREE_ENABLED */
6542
 
    return(NULL);
6543
 
}
6544
 
 
6545
 
static xmlChar*
6546
 
xmlGetPropNodeValueInternal(xmlAttrPtr prop)
6547
 
{
6548
 
    if (prop == NULL)
6549
 
        return(NULL);
6550
 
    if (prop->type == XML_ATTRIBUTE_NODE) {
6551
 
        /*
6552
 
        * Note that we return at least the empty string.
6553
 
        *   TODO: Do we really always want that?
6554
 
        */
6555
 
        if (prop->children != NULL) {
6556
 
            if ((prop->children->next == NULL) &&
6557
 
                ((prop->children->type == XML_TEXT_NODE) ||
6558
 
                (prop->children->type == XML_CDATA_SECTION_NODE)))
6559
 
            {
6560
 
                /*
6561
 
                * Optimization for the common case: only 1 text node.
6562
 
                */
6563
 
                return(xmlStrdup(prop->children->content));
6564
 
            } else {
6565
 
                xmlChar *ret;
6566
 
 
6567
 
                ret = xmlNodeListGetString(prop->doc, prop->children, 1);
6568
 
                if (ret != NULL)
6569
 
                    return(ret);
6570
 
            }
6571
 
        }
6572
 
        return(xmlStrdup((xmlChar *)""));
6573
 
    } else if (prop->type == XML_ATTRIBUTE_DECL) {
6574
 
        return(xmlStrdup(((xmlAttributePtr)prop)->defaultValue));
6575
 
    }
6576
 
    return(NULL);
6577
 
}
6578
 
 
6579
 
/**
6580
 
 * xmlHasProp:
6581
 
 * @node:  the node
6582
 
 * @name:  the attribute name
6583
 
 *
6584
 
 * Search an attribute associated to a node
6585
 
 * This function also looks in DTD attribute declaration for #FIXED or
6586
 
 * default declaration values unless DTD use has been turned off.
6587
 
 *
6588
 
 * Returns the attribute or the attribute declaration or NULL if
6589
 
 *         neither was found.
6590
 
 */
6591
 
xmlAttrPtr
6592
 
xmlHasProp(xmlNodePtr node, const xmlChar *name) {
6593
 
    xmlAttrPtr prop;
6594
 
    xmlDocPtr doc;
6595
 
 
6596
 
    if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))
6597
 
        return(NULL);
6598
 
    /*
6599
 
     * Check on the properties attached to the node
6600
 
     */
6601
 
    prop = node->properties;
6602
 
    while (prop != NULL) {
6603
 
        if (xmlStrEqual(prop->name, name))  {
6604
 
            return(prop);
6605
 
        }
6606
 
        prop = prop->next;
6607
 
    }
6608
 
    if (!xmlCheckDTD) return(NULL);
6609
 
 
6610
 
    /*
6611
 
     * Check if there is a default declaration in the internal
6612
 
     * or external subsets
6613
 
     */
6614
 
    doc =  node->doc;
6615
 
    if (doc != NULL) {
6616
 
        xmlAttributePtr attrDecl;
6617
 
        if (doc->intSubset != NULL) {
6618
 
            attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
6619
 
            if ((attrDecl == NULL) && (doc->extSubset != NULL))
6620
 
                attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
6621
 
            if ((attrDecl != NULL) && (attrDecl->defaultValue != NULL))
6622
 
              /* return attribute declaration only if a default value is given
6623
 
                 (that includes #FIXED declarations) */
6624
 
                return((xmlAttrPtr) attrDecl);
6625
 
        }
6626
 
    }
6627
 
    return(NULL);
6628
 
}
6629
 
 
6630
 
/**
6631
 
 * xmlHasNsProp:
6632
 
 * @node:  the node
6633
 
 * @name:  the attribute name
6634
 
 * @nameSpace:  the URI of the namespace
6635
 
 *
6636
 
 * Search for an attribute associated to a node
6637
 
 * This attribute has to be anchored in the namespace specified.
6638
 
 * This does the entity substitution.
6639
 
 * This function looks in DTD attribute declaration for #FIXED or
6640
 
 * default declaration values unless DTD use has been turned off.
6641
 
 * Note that a namespace of NULL indicates to use the default namespace.
6642
 
 *
6643
 
 * Returns the attribute or the attribute declaration or NULL
6644
 
 *     if neither was found.
6645
 
 */
6646
 
xmlAttrPtr
6647
 
xmlHasNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace) {
6648
 
 
6649
 
    return(xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD));
6650
 
}
6651
 
 
6652
 
/**
6653
 
 * xmlGetProp:
6654
 
 * @node:  the node
6655
 
 * @name:  the attribute name
6656
 
 *
6657
 
 * Search and get the value of an attribute associated to a node
6658
 
 * This does the entity substitution.
6659
 
 * This function looks in DTD attribute declaration for #FIXED or
6660
 
 * default declaration values unless DTD use has been turned off.
6661
 
 * NOTE: this function acts independently of namespaces associated
6662
 
 *       to the attribute. Use xmlGetNsProp() or xmlGetNoNsProp()
6663
 
 *       for namespace aware processing.
6664
 
 *
6665
 
 * Returns the attribute value or NULL if not found.
6666
 
 *     It's up to the caller to free the memory with xmlFree().
6667
 
 */
6668
 
xmlChar *
6669
 
xmlGetProp(xmlNodePtr node, const xmlChar *name) {
6670
 
    xmlAttrPtr prop;
6671
 
 
6672
 
    prop = xmlHasProp(node, name);
6673
 
    if (prop == NULL)
6674
 
        return(NULL);
6675
 
    return(xmlGetPropNodeValueInternal(prop));
6676
 
}
6677
 
 
6678
 
/**
6679
 
 * xmlGetNoNsProp:
6680
 
 * @node:  the node
6681
 
 * @name:  the attribute name
6682
 
 *
6683
 
 * Search and get the value of an attribute associated to a node
6684
 
 * This does the entity substitution.
6685
 
 * This function looks in DTD attribute declaration for #FIXED or
6686
 
 * default declaration values unless DTD use has been turned off.
6687
 
 * This function is similar to xmlGetProp except it will accept only
6688
 
 * an attribute in no namespace.
6689
 
 *
6690
 
 * Returns the attribute value or NULL if not found.
6691
 
 *     It's up to the caller to free the memory with xmlFree().
6692
 
 */
6693
 
xmlChar *
6694
 
xmlGetNoNsProp(xmlNodePtr node, const xmlChar *name) {
6695
 
    xmlAttrPtr prop;
6696
 
 
6697
 
    prop = xmlGetPropNodeInternal(node, name, NULL, xmlCheckDTD);
6698
 
    if (prop == NULL)
6699
 
        return(NULL);
6700
 
    return(xmlGetPropNodeValueInternal(prop));
6701
 
}
6702
 
 
6703
 
/**
6704
 
 * xmlGetNsProp:
6705
 
 * @node:  the node
6706
 
 * @name:  the attribute name
6707
 
 * @nameSpace:  the URI of the namespace
6708
 
 *
6709
 
 * Search and get the value of an attribute associated to a node
6710
 
 * This attribute has to be anchored in the namespace specified.
6711
 
 * This does the entity substitution.
6712
 
 * This function looks in DTD attribute declaration for #FIXED or
6713
 
 * default declaration values unless DTD use has been turned off.
6714
 
 *
6715
 
 * Returns the attribute value or NULL if not found.
6716
 
 *     It's up to the caller to free the memory with xmlFree().
6717
 
 */
6718
 
xmlChar *
6719
 
xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace) {
6720
 
    xmlAttrPtr prop;
6721
 
 
6722
 
    prop = xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD);
6723
 
    if (prop == NULL)
6724
 
        return(NULL);
6725
 
    return(xmlGetPropNodeValueInternal(prop));
6726
 
}
6727
 
 
6728
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
6729
 
/**
6730
 
 * xmlUnsetProp:
6731
 
 * @node:  the node
6732
 
 * @name:  the attribute name
6733
 
 *
6734
 
 * Remove an attribute carried by a node.
6735
 
 * This handles only attributes in no namespace.
6736
 
 * Returns 0 if successful, -1 if not found
6737
 
 */
6738
 
int
6739
 
xmlUnsetProp(xmlNodePtr node, const xmlChar *name) {
6740
 
    xmlAttrPtr prop;
6741
 
 
6742
 
    prop = xmlGetPropNodeInternal(node, name, NULL, 0);
6743
 
    if (prop == NULL)
6744
 
        return(-1);
6745
 
    xmlUnlinkNode((xmlNodePtr) prop);
6746
 
    xmlFreeProp(prop);
6747
 
    return(0);
6748
 
}
6749
 
 
6750
 
/**
6751
 
 * xmlUnsetNsProp:
6752
 
 * @node:  the node
6753
 
 * @ns:  the namespace definition
6754
 
 * @name:  the attribute name
6755
 
 *
6756
 
 * Remove an attribute carried by a node.
6757
 
 * Returns 0 if successful, -1 if not found
6758
 
 */
6759
 
int
6760
 
xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) {
6761
 
    xmlAttrPtr prop;
6762
 
 
6763
 
    prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);
6764
 
    if (prop == NULL)
6765
 
        return(-1);
6766
 
    xmlUnlinkNode((xmlNodePtr) prop);
6767
 
    xmlFreeProp(prop);
6768
 
    return(0);
6769
 
}
6770
 
#endif
6771
 
 
6772
 
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED)
6773
 
/**
6774
 
 * xmlSetProp:
6775
 
 * @node:  the node
6776
 
 * @name:  the attribute name (a QName)
6777
 
 * @value:  the attribute value
6778
 
 *
6779
 
 * Set (or reset) an attribute carried by a node.
6780
 
 * If @name has a prefix, then the corresponding
6781
 
 * namespace-binding will be used, if in scope; it is an
6782
 
 * error it there's no such ns-binding for the prefix in
6783
 
 * scope.
6784
 
 * Returns the attribute pointer.
6785
 
 *
6786
 
 */
6787
 
xmlAttrPtr
6788
 
xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
6789
 
    int len;
6790
 
    const xmlChar *nqname;
6791
 
 
6792
 
    if ((node == NULL) || (name == NULL) || (node->type != XML_ELEMENT_NODE))
6793
 
        return(NULL);
6794
 
 
6795
 
    /*
6796
 
     * handle QNames
6797
 
     */
6798
 
    nqname = xmlSplitQName3(name, &len);
6799
 
    if (nqname != NULL) {
6800
 
        xmlNsPtr ns;
6801
 
        xmlChar *prefix = xmlStrndup(name, len);
6802
 
        ns = xmlSearchNs(node->doc, node, prefix);
6803
 
        if (prefix != NULL)
6804
 
            xmlFree(prefix);
6805
 
        if (ns != NULL)
6806
 
            return(xmlSetNsProp(node, ns, nqname, value));
6807
 
    }
6808
 
    return(xmlSetNsProp(node, NULL, name, value));
6809
 
}
6810
 
 
6811
 
/**
6812
 
 * xmlSetNsProp:
6813
 
 * @node:  the node
6814
 
 * @ns:  the namespace definition
6815
 
 * @name:  the attribute name
6816
 
 * @value:  the attribute value
6817
 
 *
6818
 
 * Set (or reset) an attribute carried by a node.
6819
 
 * The ns structure must be in scope, this is not checked
6820
 
 *
6821
 
 * Returns the attribute pointer.
6822
 
 */
6823
 
xmlAttrPtr
6824
 
xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
6825
 
             const xmlChar *value)
6826
 
{
6827
 
    xmlAttrPtr prop;
6828
 
 
6829
 
    if (ns && (ns->href == NULL))
6830
 
        return(NULL);
6831
 
    prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);
6832
 
    if (prop != NULL) {
6833
 
        /*
6834
 
        * Modify the attribute's value.
6835
 
        */
6836
 
        if (prop->atype == XML_ATTRIBUTE_ID) {
6837
 
            xmlRemoveID(node->doc, prop);
6838
 
            prop->atype = XML_ATTRIBUTE_ID;
6839
 
        }
6840
 
        if (prop->children != NULL)
6841
 
            xmlFreeNodeList(prop->children);
6842
 
        prop->children = NULL;
6843
 
        prop->last = NULL;
6844
 
        prop->ns = ns;
6845
 
        if (value != NULL) {
6846
 
            xmlNodePtr tmp;
6847
 
 
6848
 
            if(!xmlCheckUTF8(value)) {
6849
 
                xmlTreeErr(XML_TREE_NOT_UTF8, (xmlNodePtr) node->doc,
6850
 
                           NULL);
6851
 
                if (node->doc != NULL)
6852
 
                    node->doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
6853
 
            }
6854
 
            prop->children = xmlNewDocText(node->doc, value);
6855
 
            prop->last = NULL;
6856
 
            tmp = prop->children;
6857
 
            while (tmp != NULL) {
6858
 
                tmp->parent = (xmlNodePtr) prop;
6859
 
                if (tmp->next == NULL)
6860
 
                    prop->last = tmp;
6861
 
                tmp = tmp->next;
6862
 
            }
6863
 
        }
6864
 
        if (prop->atype == XML_ATTRIBUTE_ID)
6865
 
            xmlAddID(NULL, node->doc, value, prop);
6866
 
        return(prop);
6867
 
    }
6868
 
    /*
6869
 
    * No equal attr found; create a new one.
6870
 
    */
6871
 
    return(xmlNewPropInternal(node, ns, name, value, 0));
6872
 
}
6873
 
 
6874
 
#endif /* LIBXML_TREE_ENABLED */
6875
 
 
6876
 
/**
6877
 
 * xmlNodeIsText:
6878
 
 * @node:  the node
6879
 
 *
6880
 
 * Is this node a Text node ?
6881
 
 * Returns 1 yes, 0 no
6882
 
 */
6883
 
int
6884
 
xmlNodeIsText(xmlNodePtr node) {
6885
 
    if (node == NULL) return(0);
6886
 
 
6887
 
    if (node->type == XML_TEXT_NODE) return(1);
6888
 
    return(0);
6889
 
}
6890
 
 
6891
 
/**
6892
 
 * xmlIsBlankNode:
6893
 
 * @node:  the node
6894
 
 *
6895
 
 * Checks whether this node is an empty or whitespace only
6896
 
 * (and possibly ignorable) text-node.
6897
 
 *
6898
 
 * Returns 1 yes, 0 no
6899
 
 */
6900
 
int
6901
 
xmlIsBlankNode(xmlNodePtr node) {
6902
 
    const xmlChar *cur;
6903
 
    if (node == NULL) return(0);
6904
 
 
6905
 
    if ((node->type != XML_TEXT_NODE) &&
6906
 
        (node->type != XML_CDATA_SECTION_NODE))
6907
 
        return(0);
6908
 
    if (node->content == NULL) return(1);
6909
 
    cur = node->content;
6910
 
    while (*cur != 0) {
6911
 
        if (!IS_BLANK_CH(*cur)) return(0);
6912
 
        cur++;
6913
 
    }
6914
 
 
6915
 
    return(1);
6916
 
}
6917
 
 
6918
 
/**
6919
 
 * xmlTextConcat:
6920
 
 * @node:  the node
6921
 
 * @content:  the content
6922
 
 * @len:  @content length
6923
 
 *
6924
 
 * Concat the given string at the end of the existing node content
6925
 
 *
6926
 
 * Returns -1 in case of error, 0 otherwise
6927
 
 */
6928
 
 
6929
 
int
6930
 
xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
6931
 
    if (node == NULL) return(-1);
6932
 
 
6933
 
    if ((node->type != XML_TEXT_NODE) &&
6934
 
        (node->type != XML_CDATA_SECTION_NODE) &&
6935
 
        (node->type != XML_COMMENT_NODE) &&
6936
 
        (node->type != XML_PI_NODE)) {
6937
 
#ifdef DEBUG_TREE
6938
 
        xmlGenericError(xmlGenericErrorContext,
6939
 
                "xmlTextConcat: node is not text nor CDATA\n");
6940
 
#endif
6941
 
        return(-1);
6942
 
    }
6943
 
    /* need to check if content is currently in the dictionary */
6944
 
    if ((node->content == (xmlChar *) &(node->properties)) ||
6945
 
        ((node->doc != NULL) && (node->doc->dict != NULL) &&
6946
 
                xmlDictOwns(node->doc->dict, node->content))) {
6947
 
        node->content = xmlStrncatNew(node->content, content, len);
6948
 
    } else {
6949
 
        node->content = xmlStrncat(node->content, content, len);
6950
 
    }
6951
 
    node->properties = NULL;
6952
 
    if (node->content == NULL)
6953
 
        return(-1);
6954
 
    return(0);
6955
 
}
6956
 
 
6957
 
/************************************************************************
6958
 
 *                                                                      *
6959
 
 *                      Output : to a FILE or in memory                 *
6960
 
 *                                                                      *
6961
 
 ************************************************************************/
6962
 
 
6963
 
/**
6964
 
 * xmlBufferCreate:
6965
 
 *
6966
 
 * routine to create an XML buffer.
6967
 
 * returns the new structure.
6968
 
 */
6969
 
xmlBufferPtr
6970
 
xmlBufferCreate(void) {
6971
 
    xmlBufferPtr ret;
6972
 
 
6973
 
    ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
6974
 
    if (ret == NULL) {
6975
 
        xmlTreeErrMemory("creating buffer");
6976
 
        return(NULL);
6977
 
    }
6978
 
    ret->use = 0;
6979
 
    ret->size = xmlDefaultBufferSize;
6980
 
    ret->alloc = xmlBufferAllocScheme;
6981
 
    ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
6982
 
    if (ret->content == NULL) {
6983
 
        xmlTreeErrMemory("creating buffer");
6984
 
        xmlFree(ret);
6985
 
        return(NULL);
6986
 
    }
6987
 
    ret->content[0] = 0;
6988
 
    ret->contentIO = NULL;
6989
 
    return(ret);
6990
 
}
6991
 
 
6992
 
/**
6993
 
 * xmlBufferCreateSize:
6994
 
 * @size: initial size of buffer
6995
 
 *
6996
 
 * routine to create an XML buffer.
6997
 
 * returns the new structure.
6998
 
 */
6999
 
xmlBufferPtr
7000
 
xmlBufferCreateSize(size_t size) {
7001
 
    xmlBufferPtr ret;
7002
 
 
7003
 
    ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
7004
 
    if (ret == NULL) {
7005
 
        xmlTreeErrMemory("creating buffer");
7006
 
        return(NULL);
7007
 
    }
7008
 
    ret->use = 0;
7009
 
    ret->alloc = xmlBufferAllocScheme;
7010
 
    ret->size = (size ? size+2 : 0);         /* +1 for ending null */
7011
 
    if (ret->size){
7012
 
        ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
7013
 
        if (ret->content == NULL) {
7014
 
            xmlTreeErrMemory("creating buffer");
7015
 
            xmlFree(ret);
7016
 
            return(NULL);
7017
 
        }
7018
 
        ret->content[0] = 0;
7019
 
    } else
7020
 
        ret->content = NULL;
7021
 
    ret->contentIO = NULL;
7022
 
    return(ret);
7023
 
}
7024
 
 
7025
 
/**
7026
 
 * xmlBufferDetach:
7027
 
 * @buf:  the buffer
7028
 
 *
7029
 
 * Remove the string contained in a buffer and gie it back to the
7030
 
 * caller. The buffer is reset to an empty content.
7031
 
 * This doesn't work with immutable buffers as they can't be reset.
7032
 
 *
7033
 
 * Returns the previous string contained by the buffer.
7034
 
 */
7035
 
xmlChar *
7036
 
xmlBufferDetach(xmlBufferPtr buf) {
7037
 
    xmlChar *ret;
7038
 
 
7039
 
    if (buf == NULL)
7040
 
        return(NULL);
7041
 
    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)
7042
 
        return(NULL);
7043
 
 
7044
 
    ret = buf->content;
7045
 
    buf->content = NULL;
7046
 
    buf->size = 0;
7047
 
    buf->use = 0;
7048
 
 
7049
 
    return ret;
7050
 
}
7051
 
 
7052
 
 
7053
 
/**
7054
 
 * xmlBufferCreateStatic:
7055
 
 * @mem: the memory area
7056
 
 * @size:  the size in byte
7057
 
 *
7058
 
 * routine to create an XML buffer from an immutable memory area.
7059
 
 * The area won't be modified nor copied, and is expected to be
7060
 
 * present until the end of the buffer lifetime.
7061
 
 *
7062
 
 * returns the new structure.
7063
 
 */
7064
 
xmlBufferPtr
7065
 
xmlBufferCreateStatic(void *mem, size_t size) {
7066
 
    xmlBufferPtr ret;
7067
 
 
7068
 
    if ((mem == NULL) || (size == 0))
7069
 
        return(NULL);
7070
 
 
7071
 
    ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
7072
 
    if (ret == NULL) {
7073
 
        xmlTreeErrMemory("creating buffer");
7074
 
        return(NULL);
7075
 
    }
7076
 
    ret->use = size;
7077
 
    ret->size = size;
7078
 
    ret->alloc = XML_BUFFER_ALLOC_IMMUTABLE;
7079
 
    ret->content = (xmlChar *) mem;
7080
 
    return(ret);
7081
 
}
7082
 
 
7083
 
/**
7084
 
 * xmlBufferSetAllocationScheme:
7085
 
 * @buf:  the buffer to tune
7086
 
 * @scheme:  allocation scheme to use
7087
 
 *
7088
 
 * Sets the allocation scheme for this buffer
7089
 
 */
7090
 
void
7091
 
xmlBufferSetAllocationScheme(xmlBufferPtr buf,
7092
 
                             xmlBufferAllocationScheme scheme) {
7093
 
    if (buf == NULL) {
7094
 
#ifdef DEBUG_BUFFER
7095
 
        xmlGenericError(xmlGenericErrorContext,
7096
 
                "xmlBufferSetAllocationScheme: buf == NULL\n");
7097
 
#endif
7098
 
        return;
7099
 
    }
7100
 
    if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
7101
 
        (buf->alloc == XML_BUFFER_ALLOC_IO)) return;
7102
 
    if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||
7103
 
        (scheme == XML_BUFFER_ALLOC_EXACT) ||
7104
 
        (scheme == XML_BUFFER_ALLOC_HYBRID) ||
7105
 
        (scheme == XML_BUFFER_ALLOC_IMMUTABLE))
7106
 
        buf->alloc = scheme;
7107
 
}
7108
 
 
7109
 
/**
7110
 
 * xmlBufferFree:
7111
 
 * @buf:  the buffer to free
7112
 
 *
7113
 
 * Frees an XML buffer. It frees both the content and the structure which
7114
 
 * encapsulate it.
7115
 
 */
7116
 
void
7117
 
xmlBufferFree(xmlBufferPtr buf) {
7118
 
    if (buf == NULL) {
7119
 
#ifdef DEBUG_BUFFER
7120
 
        xmlGenericError(xmlGenericErrorContext,
7121
 
                "xmlBufferFree: buf == NULL\n");
7122
 
#endif
7123
 
        return;
7124
 
    }
7125
 
 
7126
 
    if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
7127
 
        (buf->contentIO != NULL)) {
7128
 
        xmlFree(buf->contentIO);
7129
 
    } else if ((buf->content != NULL) &&
7130
 
        (buf->alloc != XML_BUFFER_ALLOC_IMMUTABLE)) {
7131
 
        xmlFree(buf->content);
7132
 
    }
7133
 
    xmlFree(buf);
7134
 
}
7135
 
 
7136
 
/**
7137
 
 * xmlBufferEmpty:
7138
 
 * @buf:  the buffer
7139
 
 *
7140
 
 * empty a buffer.
7141
 
 */
7142
 
void
7143
 
xmlBufferEmpty(xmlBufferPtr buf) {
7144
 
    if (buf == NULL) return;
7145
 
    if (buf->content == NULL) return;
7146
 
    buf->use = 0;
7147
 
    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) {
7148
 
        buf->content = BAD_CAST "";
7149
 
    } else if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&
7150
 
               (buf->contentIO != NULL)) {
7151
 
        size_t start_buf = buf->content - buf->contentIO;
7152
 
 
7153
 
        buf->size += start_buf;
7154
 
        buf->content = buf->contentIO;
7155
 
        buf->content[0] = 0;
7156
 
    } else {
7157
 
        buf->content[0] = 0;
7158
 
    }
7159
 
}
7160
 
 
7161
 
/**
7162
 
 * xmlBufferShrink:
7163
 
 * @buf:  the buffer to dump
7164
 
 * @len:  the number of xmlChar to remove
7165
 
 *
7166
 
 * Remove the beginning of an XML buffer.
7167
 
 *
7168
 
 * Returns the number of #xmlChar removed, or -1 in case of failure.
7169
 
 */
7170
 
int
7171
 
xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
7172
 
    if (buf == NULL) return(-1);
7173
 
    if (len == 0) return(0);
7174
 
    if (len > buf->use) return(-1);
7175
 
 
7176
 
    buf->use -= len;
7177
 
    if ((buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) ||
7178
 
        ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL))) {
7179
 
        /*
7180
 
         * we just move the content pointer, but also make sure
7181
 
         * the perceived buffer size has shrinked accordingly
7182
 
         */
7183
 
        buf->content += len;
7184
 
        buf->size -= len;
7185
 
 
7186
 
        /*
7187
 
         * sometimes though it maybe be better to really shrink
7188
 
         * on IO buffers
7189
 
         */
7190
 
        if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
7191
 
            size_t start_buf = buf->content - buf->contentIO;
7192
 
            if (start_buf >= buf->size) {
7193
 
                memmove(buf->contentIO, &buf->content[0], buf->use);
7194
 
                buf->content = buf->contentIO;
7195
 
                buf->content[buf->use] = 0;
7196
 
                buf->size += start_buf;
7197
 
            }
7198
 
        }
7199
 
    } else {
7200
 
        memmove(buf->content, &buf->content[len], buf->use);
7201
 
        buf->content[buf->use] = 0;
7202
 
    }
7203
 
    return(len);
7204
 
}
7205
 
 
7206
 
/**
7207
 
 * xmlBufferGrow:
7208
 
 * @buf:  the buffer
7209
 
 * @len:  the minimum free size to allocate
7210
 
 *
7211
 
 * Grow the available space of an XML buffer.
7212
 
 *
7213
 
 * Returns the new available space or -1 in case of error
7214
 
 */
7215
 
int
7216
 
xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
7217
 
    int size;
7218
 
    xmlChar *newbuf;
7219
 
 
7220
 
    if (buf == NULL) return(-1);
7221
 
 
7222
 
    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
7223
 
    if (len + buf->use < buf->size) return(0);
7224
 
 
7225
 
    /*
7226
 
     * Windows has a BIG problem on realloc timing, so we try to double
7227
 
     * the buffer size (if that's enough) (bug 146697)
7228
 
     * Apparently BSD too, and it's probably best for linux too
7229
 
     * On an embedded system this may be something to change
7230
 
     */
7231
 
#if 1
7232
 
    if (buf->size > len)
7233
 
        size = buf->size * 2;
7234
 
    else
7235
 
        size = buf->use + len + 100;
7236
 
#else
7237
 
    size = buf->use + len + 100;
7238
 
#endif
7239
 
 
7240
 
    if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
7241
 
        size_t start_buf = buf->content - buf->contentIO;
7242
 
 
7243
 
        newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size);
7244
 
        if (newbuf == NULL) {
7245
 
            xmlTreeErrMemory("growing buffer");
7246
 
            return(-1);
7247
 
        }
7248
 
        buf->contentIO = newbuf;
7249
 
        buf->content = newbuf + start_buf;
7250
 
    } else {
7251
 
        newbuf = (xmlChar *) xmlRealloc(buf->content, size);
7252
 
        if (newbuf == NULL) {
7253
 
            xmlTreeErrMemory("growing buffer");
7254
 
            return(-1);
7255
 
        }
7256
 
        buf->content = newbuf;
7257
 
    }
7258
 
    buf->size = size;
7259
 
    return(buf->size - buf->use);
7260
 
}
7261
 
 
7262
 
/**
7263
 
 * xmlBufferDump:
7264
 
 * @file:  the file output
7265
 
 * @buf:  the buffer to dump
7266
 
 *
7267
 
 * Dumps an XML buffer to  a FILE *.
7268
 
 * Returns the number of #xmlChar written
7269
 
 */
7270
 
int
7271
 
xmlBufferDump(FILE *file, xmlBufferPtr buf) {
7272
 
    int ret;
7273
 
 
7274
 
    if (buf == NULL) {
7275
 
#ifdef DEBUG_BUFFER
7276
 
        xmlGenericError(xmlGenericErrorContext,
7277
 
                "xmlBufferDump: buf == NULL\n");
7278
 
#endif
7279
 
        return(0);
7280
 
    }
7281
 
    if (buf->content == NULL) {
7282
 
#ifdef DEBUG_BUFFER
7283
 
        xmlGenericError(xmlGenericErrorContext,
7284
 
                "xmlBufferDump: buf->content == NULL\n");
7285
 
#endif
7286
 
        return(0);
7287
 
    }
7288
 
    if (file == NULL)
7289
 
        file = stdout;
7290
 
    ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
7291
 
    return(ret);
7292
 
}
7293
 
 
7294
 
/**
7295
 
 * xmlBufferContent:
7296
 
 * @buf:  the buffer
7297
 
 *
7298
 
 * Function to extract the content of a buffer
7299
 
 *
7300
 
 * Returns the internal content
7301
 
 */
7302
 
 
7303
 
const xmlChar *
7304
 
xmlBufferContent(const xmlBufferPtr buf)
7305
 
{
7306
 
    if(!buf)
7307
 
        return NULL;
7308
 
 
7309
 
    return buf->content;
7310
 
}
7311
 
 
7312
 
/**
7313
 
 * xmlBufferLength:
7314
 
 * @buf:  the buffer
7315
 
 *
7316
 
 * Function to get the length of a buffer
7317
 
 *
7318
 
 * Returns the length of data in the internal content
7319
 
 */
7320
 
 
7321
 
int
7322
 
xmlBufferLength(const xmlBufferPtr buf)
7323
 
{
7324
 
    if(!buf)
7325
 
        return 0;
7326
 
 
7327
 
    return buf->use;
7328
 
}
7329
 
 
7330
 
/**
7331
 
 * xmlBufferResize:
7332
 
 * @buf:  the buffer to resize
7333
 
 * @size:  the desired size
7334
 
 *
7335
 
 * Resize a buffer to accommodate minimum size of @size.
7336
 
 *
7337
 
 * Returns  0 in case of problems, 1 otherwise
7338
 
 */
7339
 
int
7340
 
xmlBufferResize(xmlBufferPtr buf, unsigned int size)
7341
 
{
7342
 
    unsigned int newSize;
7343
 
    xmlChar* rebuf = NULL;
7344
 
    size_t start_buf;
7345
 
 
7346
 
    if (buf == NULL)
7347
 
        return(0);
7348
 
 
7349
 
    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
7350
 
 
7351
 
    /* Don't resize if we don't have to */
7352
 
    if (size < buf->size)
7353
 
        return 1;
7354
 
 
7355
 
    /* figure out new size */
7356
 
    switch (buf->alloc){
7357
 
        case XML_BUFFER_ALLOC_IO:
7358
 
        case XML_BUFFER_ALLOC_DOUBLEIT:
7359
 
            /*take care of empty case*/
7360
 
            newSize = (buf->size ? buf->size*2 : size + 10);
7361
 
            while (size > newSize) {
7362
 
                if (newSize > UINT_MAX / 2) {
7363
 
                    xmlTreeErrMemory("growing buffer");
7364
 
                    return 0;
7365
 
                }
7366
 
                newSize *= 2;
7367
 
            }
7368
 
            break;
7369
 
        case XML_BUFFER_ALLOC_EXACT:
7370
 
            newSize = size+10;
7371
 
            break;
7372
 
        case XML_BUFFER_ALLOC_HYBRID:
7373
 
            if (buf->use < BASE_BUFFER_SIZE)
7374
 
                newSize = size;
7375
 
            else {
7376
 
                newSize = buf->size * 2;
7377
 
                while (size > newSize) {
7378
 
                    if (newSize > UINT_MAX / 2) {
7379
 
                        xmlTreeErrMemory("growing buffer");
7380
 
                        return 0;
7381
 
                    }
7382
 
                    newSize *= 2;
7383
 
                }
7384
 
            }
7385
 
            break;
7386
 
 
7387
 
        default:
7388
 
            newSize = size+10;
7389
 
            break;
7390
 
    }
7391
 
 
7392
 
    if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
7393
 
        start_buf = buf->content - buf->contentIO;
7394
 
 
7395
 
        if (start_buf > newSize) {
7396
 
            /* move data back to start */
7397
 
            memmove(buf->contentIO, buf->content, buf->use);
7398
 
            buf->content = buf->contentIO;
7399
 
            buf->content[buf->use] = 0;
7400
 
            buf->size += start_buf;
7401
 
        } else {
7402
 
            rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize);
7403
 
            if (rebuf == NULL) {
7404
 
                xmlTreeErrMemory("growing buffer");
7405
 
                return 0;
7406
 
            }
7407
 
            buf->contentIO = rebuf;
7408
 
            buf->content = rebuf + start_buf;
7409
 
        }
7410
 
    } else {
7411
 
        if (buf->content == NULL) {
7412
 
            rebuf = (xmlChar *) xmlMallocAtomic(newSize);
7413
 
        } else if (buf->size - buf->use < 100) {
7414
 
            rebuf = (xmlChar *) xmlRealloc(buf->content, newSize);
7415
 
        } else {
7416
 
            /*
7417
 
             * if we are reallocating a buffer far from being full, it's
7418
 
             * better to make a new allocation and copy only the used range
7419
 
             * and free the old one.
7420
 
             */
7421
 
            rebuf = (xmlChar *) xmlMallocAtomic(newSize);
7422
 
            if (rebuf != NULL) {
7423
 
                memcpy(rebuf, buf->content, buf->use);
7424
 
                xmlFree(buf->content);
7425
 
                rebuf[buf->use] = 0;
7426
 
            }
7427
 
        }
7428
 
        if (rebuf == NULL) {
7429
 
            xmlTreeErrMemory("growing buffer");
7430
 
            return 0;
7431
 
        }
7432
 
        buf->content = rebuf;
7433
 
    }
7434
 
    buf->size = newSize;
7435
 
 
7436
 
    return 1;
7437
 
}
7438
 
 
7439
 
/**
7440
 
 * xmlBufferAdd:
7441
 
 * @buf:  the buffer to dump
7442
 
 * @str:  the #xmlChar string
7443
 
 * @len:  the number of #xmlChar to add
7444
 
 *
7445
 
 * Add a string range to an XML buffer. if len == -1, the length of
7446
 
 * str is recomputed.
7447
 
 *
7448
 
 * Returns 0 successful, a positive error code number otherwise
7449
 
 *         and -1 in case of internal or API error.
7450
 
 */
7451
 
int
7452
 
xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
7453
 
    unsigned int needSize;
7454
 
 
7455
 
    if ((str == NULL) || (buf == NULL)) {
7456
 
        return -1;
7457
 
    }
7458
 
    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
7459
 
    if (len < -1) {
7460
 
#ifdef DEBUG_BUFFER
7461
 
        xmlGenericError(xmlGenericErrorContext,
7462
 
                "xmlBufferAdd: len < 0\n");
7463
 
#endif
7464
 
        return -1;
7465
 
    }
7466
 
    if (len == 0) return 0;
7467
 
 
7468
 
    if (len < 0)
7469
 
        len = xmlStrlen(str);
7470
 
 
7471
 
    if (len < 0) return -1;
7472
 
    if (len == 0) return 0;
7473
 
 
7474
 
    needSize = buf->use + len + 2;
7475
 
    if (needSize > buf->size){
7476
 
        if (!xmlBufferResize(buf, needSize)){
7477
 
            xmlTreeErrMemory("growing buffer");
7478
 
            return XML_ERR_NO_MEMORY;
7479
 
        }
7480
 
    }
7481
 
 
7482
 
    memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
7483
 
    buf->use += len;
7484
 
    buf->content[buf->use] = 0;
7485
 
    return 0;
7486
 
}
7487
 
 
7488
 
/**
7489
 
 * xmlBufferAddHead:
7490
 
 * @buf:  the buffer
7491
 
 * @str:  the #xmlChar string
7492
 
 * @len:  the number of #xmlChar to add
7493
 
 *
7494
 
 * Add a string range to the beginning of an XML buffer.
7495
 
 * if len == -1, the length of @str is recomputed.
7496
 
 *
7497
 
 * Returns 0 successful, a positive error code number otherwise
7498
 
 *         and -1 in case of internal or API error.
7499
 
 */
7500
 
int
7501
 
xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
7502
 
    unsigned int needSize;
7503
 
 
7504
 
    if (buf == NULL)
7505
 
        return(-1);
7506
 
    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
7507
 
    if (str == NULL) {
7508
 
#ifdef DEBUG_BUFFER
7509
 
        xmlGenericError(xmlGenericErrorContext,
7510
 
                "xmlBufferAddHead: str == NULL\n");
7511
 
#endif
7512
 
        return -1;
7513
 
    }
7514
 
    if (len < -1) {
7515
 
#ifdef DEBUG_BUFFER
7516
 
        xmlGenericError(xmlGenericErrorContext,
7517
 
                "xmlBufferAddHead: len < 0\n");
7518
 
#endif
7519
 
        return -1;
7520
 
    }
7521
 
    if (len == 0) return 0;
7522
 
 
7523
 
    if (len < 0)
7524
 
        len = xmlStrlen(str);
7525
 
 
7526
 
    if (len <= 0) return -1;
7527
 
 
7528
 
    if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
7529
 
        size_t start_buf = buf->content - buf->contentIO;
7530
 
 
7531
 
        if (start_buf > (unsigned int) len) {
7532
 
            /*
7533
 
             * We can add it in the space previously shrinked
7534
 
             */
7535
 
            buf->content -= len;
7536
 
            memmove(&buf->content[0], str, len);
7537
 
            buf->use += len;
7538
 
            buf->size += len;
7539
 
            return(0);
7540
 
        }
7541
 
    }
7542
 
    needSize = buf->use + len + 2;
7543
 
    if (needSize > buf->size){
7544
 
        if (!xmlBufferResize(buf, needSize)){
7545
 
            xmlTreeErrMemory("growing buffer");
7546
 
            return XML_ERR_NO_MEMORY;
7547
 
        }
7548
 
    }
7549
 
 
7550
 
    memmove(&buf->content[len], &buf->content[0], buf->use);
7551
 
    memmove(&buf->content[0], str, len);
7552
 
    buf->use += len;
7553
 
    buf->content[buf->use] = 0;
7554
 
    return 0;
7555
 
}
7556
 
 
7557
 
/**
7558
 
 * xmlBufferCat:
7559
 
 * @buf:  the buffer to add to
7560
 
 * @str:  the #xmlChar string
7561
 
 *
7562
 
 * Append a zero terminated string to an XML buffer.
7563
 
 *
7564
 
 * Returns 0 successful, a positive error code number otherwise
7565
 
 *         and -1 in case of internal or API error.
7566
 
 */
7567
 
int
7568
 
xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
7569
 
    if (buf == NULL)
7570
 
        return(-1);
7571
 
    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
7572
 
    if (str == NULL) return -1;
7573
 
    return xmlBufferAdd(buf, str, -1);
7574
 
}
7575
 
 
7576
 
/**
7577
 
 * xmlBufferCCat:
7578
 
 * @buf:  the buffer to dump
7579
 
 * @str:  the C char string
7580
 
 *
7581
 
 * Append a zero terminated C string to an XML buffer.
7582
 
 *
7583
 
 * Returns 0 successful, a positive error code number otherwise
7584
 
 *         and -1 in case of internal or API error.
7585
 
 */
7586
 
int
7587
 
xmlBufferCCat(xmlBufferPtr buf, const char *str) {
7588
 
    const char *cur;
7589
 
 
7590
 
    if (buf == NULL)
7591
 
        return(-1);
7592
 
    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
7593
 
    if (str == NULL) {
7594
 
#ifdef DEBUG_BUFFER
7595
 
        xmlGenericError(xmlGenericErrorContext,
7596
 
                "xmlBufferCCat: str == NULL\n");
7597
 
#endif
7598
 
        return -1;
7599
 
    }
7600
 
    for (cur = str;*cur != 0;cur++) {
7601
 
        if (buf->use  + 10 >= buf->size) {
7602
 
            if (!xmlBufferResize(buf, buf->use+10)){
7603
 
                xmlTreeErrMemory("growing buffer");
7604
 
                return XML_ERR_NO_MEMORY;
7605
 
            }
7606
 
        }
7607
 
        buf->content[buf->use++] = *cur;
7608
 
    }
7609
 
    buf->content[buf->use] = 0;
7610
 
    return 0;
7611
 
}
7612
 
 
7613
 
/**
7614
 
 * xmlBufferWriteCHAR:
7615
 
 * @buf:  the XML buffer
7616
 
 * @string:  the string to add
7617
 
 *
7618
 
 * routine which manages and grows an output buffer. This one adds
7619
 
 * xmlChars at the end of the buffer.
7620
 
 */
7621
 
void
7622
 
xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
7623
 
    if (buf == NULL)
7624
 
        return;
7625
 
    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
7626
 
    xmlBufferCat(buf, string);
7627
 
}
7628
 
 
7629
 
/**
7630
 
 * xmlBufferWriteChar:
7631
 
 * @buf:  the XML buffer output
7632
 
 * @string:  the string to add
7633
 
 *
7634
 
 * routine which manage and grows an output buffer. This one add
7635
 
 * C chars at the end of the array.
7636
 
 */
7637
 
void
7638
 
xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
7639
 
    if (buf == NULL)
7640
 
        return;
7641
 
    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
7642
 
    xmlBufferCCat(buf, string);
7643
 
}
7644
 
 
7645
 
 
7646
 
/**
7647
 
 * xmlBufferWriteQuotedString:
7648
 
 * @buf:  the XML buffer output
7649
 
 * @string:  the string to add
7650
 
 *
7651
 
 * routine which manage and grows an output buffer. This one writes
7652
 
 * a quoted or double quoted #xmlChar string, checking first if it holds
7653
 
 * quote or double-quotes internally
7654
 
 */
7655
 
void
7656
 
xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
7657
 
    const xmlChar *cur, *base;
7658
 
    if (buf == NULL)
7659
 
        return;
7660
 
    if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return;
7661
 
    if (xmlStrchr(string, '\"')) {
7662
 
        if (xmlStrchr(string, '\'')) {
7663
 
#ifdef DEBUG_BUFFER
7664
 
            xmlGenericError(xmlGenericErrorContext,
7665
 
 "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
7666
 
#endif
7667
 
            xmlBufferCCat(buf, "\"");
7668
 
            base = cur = string;
7669
 
            while(*cur != 0){
7670
 
                if(*cur == '"'){
7671
 
                    if (base != cur)
7672
 
                        xmlBufferAdd(buf, base, cur - base);
7673
 
                    xmlBufferAdd(buf, BAD_CAST "&quot;", 6);
7674
 
                    cur++;
7675
 
                    base = cur;
7676
 
                }
7677
 
                else {
7678
 
                    cur++;
7679
 
                }
7680
 
            }
7681
 
            if (base != cur)
7682
 
                xmlBufferAdd(buf, base, cur - base);
7683
 
            xmlBufferCCat(buf, "\"");
7684
 
        }
7685
 
        else{
7686
 
            xmlBufferCCat(buf, "\'");
7687
 
            xmlBufferCat(buf, string);
7688
 
            xmlBufferCCat(buf, "\'");
7689
 
        }
7690
 
    } else {
7691
 
        xmlBufferCCat(buf, "\"");
7692
 
        xmlBufferCat(buf, string);
7693
 
        xmlBufferCCat(buf, "\"");
7694
 
    }
7695
 
}
7696
 
 
7697
 
 
7698
 
/**
7699
 
 * xmlGetDocCompressMode:
7700
 
 * @doc:  the document
7701
 
 *
7702
 
 * get the compression ratio for a document, ZLIB based
7703
 
 * Returns 0 (uncompressed) to 9 (max compression)
7704
 
 */
7705
 
int
7706
 
xmlGetDocCompressMode (xmlDocPtr doc) {
7707
 
    if (doc == NULL) return(-1);
7708
 
    return(doc->compression);
7709
 
}
7710
 
 
7711
 
/**
7712
 
 * xmlSetDocCompressMode:
7713
 
 * @doc:  the document
7714
 
 * @mode:  the compression ratio
7715
 
 *
7716
 
 * set the compression ratio for a document, ZLIB based
7717
 
 * Correct values: 0 (uncompressed) to 9 (max compression)
7718
 
 */
7719
 
void
7720
 
xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
7721
 
    if (doc == NULL) return;
7722
 
    if (mode < 0) doc->compression = 0;
7723
 
    else if (mode > 9) doc->compression = 9;
7724
 
    else doc->compression = mode;
7725
 
}
7726
 
 
7727
 
/**
7728
 
 * xmlGetCompressMode:
7729
 
 *
7730
 
 * get the default compression mode used, ZLIB based.
7731
 
 * Returns 0 (uncompressed) to 9 (max compression)
7732
 
 */
7733
 
int
7734
 
xmlGetCompressMode(void)
7735
 
{
7736
 
    return (xmlCompressMode);
7737
 
}
7738
 
 
7739
 
/**
7740
 
 * xmlSetCompressMode:
7741
 
 * @mode:  the compression ratio
7742
 
 *
7743
 
 * set the default compression mode used, ZLIB based
7744
 
 * Correct values: 0 (uncompressed) to 9 (max compression)
7745
 
 */
7746
 
void
7747
 
xmlSetCompressMode(int mode) {
7748
 
    if (mode < 0) xmlCompressMode = 0;
7749
 
    else if (mode > 9) xmlCompressMode = 9;
7750
 
    else xmlCompressMode = mode;
7751
 
}
7752
 
 
7753
 
#define XML_TREE_NSMAP_PARENT -1
7754
 
#define XML_TREE_NSMAP_XML -2
7755
 
#define XML_TREE_NSMAP_DOC -3
7756
 
#define XML_TREE_NSMAP_CUSTOM -4
7757
 
 
7758
 
typedef struct xmlNsMapItem *xmlNsMapItemPtr;
7759
 
struct xmlNsMapItem {
7760
 
    xmlNsMapItemPtr next;
7761
 
    xmlNsMapItemPtr prev;
7762
 
    xmlNsPtr oldNs; /* old ns decl reference */
7763
 
    xmlNsPtr newNs; /* new ns decl reference */
7764
 
    int shadowDepth; /* Shadowed at this depth */
7765
 
    /*
7766
 
    * depth:
7767
 
    * >= 0 == @node's ns-decls
7768
 
    * -1   == @parent's ns-decls
7769
 
    * -2   == the doc->oldNs XML ns-decl
7770
 
    * -3   == the doc->oldNs storage ns-decls
7771
 
    * -4   == ns-decls provided via custom ns-handling
7772
 
    */
7773
 
    int depth;
7774
 
};
7775
 
 
7776
 
typedef struct xmlNsMap *xmlNsMapPtr;
7777
 
struct xmlNsMap {
7778
 
    xmlNsMapItemPtr first;
7779
 
    xmlNsMapItemPtr last;
7780
 
    xmlNsMapItemPtr pool;
7781
 
};
7782
 
 
7783
 
#define XML_NSMAP_NOTEMPTY(m) (((m) != NULL) && ((m)->first != NULL))
7784
 
#define XML_NSMAP_FOREACH(m, i) for (i = (m)->first; i != NULL; i = (i)->next)
7785
 
#define XML_NSMAP_POP(m, i) \
7786
 
    i = (m)->last; \
7787
 
    (m)->last = (i)->prev; \
7788
 
    if ((m)->last == NULL) \
7789
 
        (m)->first = NULL; \
7790
 
    else \
7791
 
        (m)->last->next = NULL; \
7792
 
    (i)->next = (m)->pool; \
7793
 
    (m)->pool = i;
7794
 
 
7795
 
/*
7796
 
* xmlDOMWrapNsMapFree:
7797
 
* @map: the ns-map
7798
 
*
7799
 
* Frees the ns-map
7800
 
*/
7801
 
static void
7802
 
xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap)
7803
 
{
7804
 
    xmlNsMapItemPtr cur, tmp;
7805
 
 
7806
 
    if (nsmap == NULL)
7807
 
        return;
7808
 
    cur = nsmap->pool;
7809
 
    while (cur != NULL) {
7810
 
        tmp = cur;
7811
 
        cur = cur->next;
7812
 
        xmlFree(tmp);
7813
 
    }
7814
 
    cur = nsmap->first;
7815
 
    while (cur != NULL) {
7816
 
        tmp = cur;
7817
 
        cur = cur->next;
7818
 
        xmlFree(tmp);
7819
 
    }
7820
 
    xmlFree(nsmap);
7821
 
}
7822
 
 
7823
 
/*
7824
 
* xmlDOMWrapNsMapAddItem:
7825
 
* @map: the ns-map
7826
 
* @oldNs: the old ns-struct
7827
 
* @newNs: the new ns-struct
7828
 
* @depth: depth and ns-kind information
7829
 
*
7830
 
* Adds an ns-mapping item.
7831
 
*/
7832
 
static xmlNsMapItemPtr
7833
 
xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position,
7834
 
                       xmlNsPtr oldNs, xmlNsPtr newNs, int depth)
7835
 
{
7836
 
    xmlNsMapItemPtr ret;
7837
 
    xmlNsMapPtr map;
7838
 
 
7839
 
    if (nsmap == NULL)
7840
 
        return(NULL);
7841
 
    if ((position != -1) && (position != 0))
7842
 
        return(NULL);
7843
 
    map = *nsmap;
7844
 
 
7845
 
    if (map == NULL) {
7846
 
        /*
7847
 
        * Create the ns-map.
7848
 
        */
7849
 
        map = (xmlNsMapPtr) xmlMalloc(sizeof(struct xmlNsMap));
7850
 
        if (map == NULL) {
7851
 
            xmlTreeErrMemory("allocating namespace map");
7852
 
            return (NULL);
7853
 
        }
7854
 
        memset(map, 0, sizeof(struct xmlNsMap));
7855
 
        *nsmap = map;
7856
 
    }
7857
 
 
7858
 
    if (map->pool != NULL) {
7859
 
        /*
7860
 
        * Reuse an item from the pool.
7861
 
        */
7862
 
        ret = map->pool;
7863
 
        map->pool = ret->next;
7864
 
        memset(ret, 0, sizeof(struct xmlNsMapItem));
7865
 
    } else {
7866
 
        /*
7867
 
        * Create a new item.
7868
 
        */
7869
 
        ret = (xmlNsMapItemPtr) xmlMalloc(sizeof(struct xmlNsMapItem));
7870
 
        if (ret == NULL) {
7871
 
            xmlTreeErrMemory("allocating namespace map item");
7872
 
            return (NULL);
7873
 
        }
7874
 
        memset(ret, 0, sizeof(struct xmlNsMapItem));
7875
 
    }
7876
 
 
7877
 
    if (map->first == NULL) {
7878
 
        /*
7879
 
        * First ever.
7880
 
        */
7881
 
        map->first = ret;
7882
 
        map->last = ret;
7883
 
    } else if (position == -1) {
7884
 
        /*
7885
 
        * Append.
7886
 
        */
7887
 
        ret->prev = map->last;
7888
 
        map->last->next = ret;
7889
 
        map->last = ret;
7890
 
    } else if (position == 0) {
7891
 
        /*
7892
 
        * Set on first position.
7893
 
        */
7894
 
        map->first->prev = ret;
7895
 
        ret->next = map->first;
7896
 
        map->first = ret;
7897
 
    } else
7898
 
        return(NULL);
7899
 
 
7900
 
    ret->oldNs = oldNs;
7901
 
    ret->newNs = newNs;
7902
 
    ret->shadowDepth = -1;
7903
 
    ret->depth = depth;
7904
 
    return (ret);
7905
 
}
7906
 
 
7907
 
/*
7908
 
* xmlDOMWrapStoreNs:
7909
 
* @doc: the doc
7910
 
* @nsName: the namespace name
7911
 
* @prefix: the prefix
7912
 
*
7913
 
* Creates or reuses an xmlNs struct on doc->oldNs with
7914
 
* the given prefix and namespace name.
7915
 
*
7916
 
* Returns the aquired ns struct or NULL in case of an API
7917
 
*         or internal error.
7918
 
*/
7919
 
static xmlNsPtr
7920
 
xmlDOMWrapStoreNs(xmlDocPtr doc,
7921
 
                   const xmlChar *nsName,
7922
 
                   const xmlChar *prefix)
7923
 
{
7924
 
    xmlNsPtr ns;
7925
 
 
7926
 
    if (doc == NULL)
7927
 
        return (NULL);
7928
 
    ns = xmlTreeEnsureXMLDecl(doc);
7929
 
    if (ns == NULL)
7930
 
        return (NULL);
7931
 
    if (ns->next != NULL) {
7932
 
        /* Reuse. */
7933
 
        ns = ns->next;
7934
 
        while (ns != NULL) {
7935
 
            if (((ns->prefix == prefix) ||
7936
 
                xmlStrEqual(ns->prefix, prefix)) &&
7937
 
                xmlStrEqual(ns->href, nsName)) {
7938
 
                return (ns);
7939
 
            }
7940
 
            if (ns->next == NULL)
7941
 
                break;
7942
 
            ns = ns->next;
7943
 
        }
7944
 
    }
7945
 
    /* Create. */
7946
 
    if (ns != NULL) {
7947
 
        ns->next = xmlNewNs(NULL, nsName, prefix);
7948
 
        return (ns->next);
7949
 
    }
7950
 
    return(NULL);
7951
 
}
7952
 
 
7953
 
/*
7954
 
* xmlDOMWrapNewCtxt:
7955
 
*
7956
 
* Allocates and initializes a new DOM-wrapper context.
7957
 
*
7958
 
* Returns the xmlDOMWrapCtxtPtr or NULL in case of an internal errror.
7959
 
*/
7960
 
xmlDOMWrapCtxtPtr
7961
 
xmlDOMWrapNewCtxt(void)
7962
 
{
7963
 
    xmlDOMWrapCtxtPtr ret;
7964
 
 
7965
 
    ret = xmlMalloc(sizeof(xmlDOMWrapCtxt));
7966
 
    if (ret == NULL) {
7967
 
        xmlTreeErrMemory("allocating DOM-wrapper context");
7968
 
        return (NULL);
7969
 
    }
7970
 
    memset(ret, 0, sizeof(xmlDOMWrapCtxt));
7971
 
    return (ret);
7972
 
}
7973
 
 
7974
 
/*
7975
 
* xmlDOMWrapFreeCtxt:
7976
 
* @ctxt: the DOM-wrapper context
7977
 
*
7978
 
* Frees the DOM-wrapper context.
7979
 
*/
7980
 
void
7981
 
xmlDOMWrapFreeCtxt(xmlDOMWrapCtxtPtr ctxt)
7982
 
{
7983
 
    if (ctxt == NULL)
7984
 
        return;
7985
 
    if (ctxt->namespaceMap != NULL)
7986
 
        xmlDOMWrapNsMapFree((xmlNsMapPtr) ctxt->namespaceMap);
7987
 
    /*
7988
 
    * TODO: Store the namespace map in the context.
7989
 
    */
7990
 
    xmlFree(ctxt);
7991
 
}
7992
 
 
7993
 
/*
7994
 
* xmlTreeLookupNsListByPrefix:
7995
 
* @nsList: a list of ns-structs
7996
 
* @prefix: the searched prefix
7997
 
*
7998
 
* Searches for a ns-decl with the given prefix in @nsList.
7999
 
*
8000
 
* Returns the ns-decl if found, NULL if not found and on
8001
 
*         API errors.
8002
 
*/
8003
 
static xmlNsPtr
8004
 
xmlTreeNSListLookupByPrefix(xmlNsPtr nsList, const xmlChar *prefix)
8005
 
{
8006
 
    if (nsList == NULL)
8007
 
        return (NULL);
8008
 
    {
8009
 
        xmlNsPtr ns;
8010
 
        ns = nsList;
8011
 
        do {
8012
 
            if ((prefix == ns->prefix) ||
8013
 
                xmlStrEqual(prefix, ns->prefix)) {
8014
 
                return (ns);
8015
 
            }
8016
 
            ns = ns->next;
8017
 
        } while (ns != NULL);
8018
 
    }
8019
 
    return (NULL);
8020
 
}
8021
 
 
8022
 
/*
8023
 
*
8024
 
* xmlDOMWrapNSNormGatherInScopeNs:
8025
 
* @map: the namespace map
8026
 
* @node: the node to start with
8027
 
*
8028
 
* Puts in-scope namespaces into the ns-map.
8029
 
*
8030
 
* Returns 0 on success, -1 on API or internal errors.
8031
 
*/
8032
 
static int
8033
 
xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr *map,
8034
 
                                xmlNodePtr node)
8035
 
{
8036
 
    xmlNodePtr cur;
8037
 
    xmlNsPtr ns;
8038
 
    xmlNsMapItemPtr mi;
8039
 
    int shadowed;
8040
 
 
8041
 
    if ((map == NULL) || (*map != NULL))
8042
 
        return (-1);
8043
 
    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
8044
 
        return (-1);
8045
 
    /*
8046
 
    * Get in-scope ns-decls of @parent.
8047
 
    */
8048
 
    cur = node;
8049
 
    while ((cur != NULL) && (cur != (xmlNodePtr) cur->doc)) {
8050
 
        if (cur->type == XML_ELEMENT_NODE) {
8051
 
            if (cur->nsDef != NULL) {
8052
 
                ns = cur->nsDef;
8053
 
                do {
8054
 
                    shadowed = 0;
8055
 
                    if (XML_NSMAP_NOTEMPTY(*map)) {
8056
 
                        /*
8057
 
                        * Skip shadowed prefixes.
8058
 
                        */
8059
 
                        XML_NSMAP_FOREACH(*map, mi) {
8060
 
                            if ((ns->prefix == mi->newNs->prefix) ||
8061
 
                                xmlStrEqual(ns->prefix, mi->newNs->prefix)) {
8062
 
                                shadowed = 1;
8063
 
                                break;
8064
 
                            }
8065
 
                        }
8066
 
                    }
8067
 
                    /*
8068
 
                    * Insert mapping.
8069
 
                    */
8070
 
                    mi = xmlDOMWrapNsMapAddItem(map, 0, NULL,
8071
 
                        ns, XML_TREE_NSMAP_PARENT);
8072
 
                    if (mi == NULL)
8073
 
                        return (-1);
8074
 
                    if (shadowed)
8075
 
                        mi->shadowDepth = 0;
8076
 
                    ns = ns->next;
8077
 
                } while (ns != NULL);
8078
 
            }
8079
 
        }
8080
 
        cur = cur->parent;
8081
 
    }
8082
 
    return (0);
8083
 
}
8084
 
 
8085
 
/*
8086
 
* XML_TREE_ADOPT_STR: If we have a dest-dict, put @str in the dict;
8087
 
* otherwise copy it, when it was in the source-dict.
8088
 
*/
8089
 
#define XML_TREE_ADOPT_STR(str) \
8090
 
    if (adoptStr && (str != NULL)) { \
8091
 
        if (destDoc->dict) { \
8092
 
            const xmlChar *old = str;   \
8093
 
            str = xmlDictLookup(destDoc->dict, str, -1); \
8094
 
            if ((sourceDoc == NULL) || (sourceDoc->dict == NULL) || \
8095
 
                (!xmlDictOwns(sourceDoc->dict, old))) \
8096
 
                xmlFree((char *)old); \
8097
 
        } else if ((sourceDoc) && (sourceDoc->dict) && \
8098
 
            xmlDictOwns(sourceDoc->dict, str)) { \
8099
 
            str = BAD_CAST xmlStrdup(str); \
8100
 
        } \
8101
 
    }
8102
 
 
8103
 
/*
8104
 
* XML_TREE_ADOPT_STR_2: If @str was in the source-dict, then
8105
 
* put it in dest-dict or copy it.
8106
 
*/
8107
 
#define XML_TREE_ADOPT_STR_2(str) \
8108
 
    if (adoptStr && (str != NULL) && (sourceDoc != NULL) && \
8109
 
        (sourceDoc->dict != NULL) && \
8110
 
        xmlDictOwns(sourceDoc->dict, cur->content)) { \
8111
 
        if (destDoc->dict) \
8112
 
            cur->content = (xmlChar *) \
8113
 
                xmlDictLookup(destDoc->dict, cur->content, -1); \
8114
 
        else \
8115
 
            cur->content = xmlStrdup(BAD_CAST cur->content); \
8116
 
    }
8117
 
 
8118
 
/*
8119
 
* xmlDOMWrapNSNormAddNsMapItem2:
8120
 
*
8121
 
* For internal use. Adds a ns-decl mapping.
8122
 
*
8123
 
* Returns 0 on success, -1 on internal errors.
8124
 
*/
8125
 
static int
8126
 
xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr **list, int *size, int *number,
8127
 
                        xmlNsPtr oldNs, xmlNsPtr newNs)
8128
 
{
8129
 
    if (*list == NULL) {
8130
 
        *list = (xmlNsPtr *) xmlMalloc(6 * sizeof(xmlNsPtr));
8131
 
        if (*list == NULL) {
8132
 
            xmlTreeErrMemory("alloc ns map item");
8133
 
            return(-1);
8134
 
        }
8135
 
        *size = 3;
8136
 
        *number = 0;
8137
 
    } else if ((*number) >= (*size)) {
8138
 
        *size *= 2;
8139
 
        *list = (xmlNsPtr *) xmlRealloc(*list,
8140
 
            (*size) * 2 * sizeof(xmlNsPtr));
8141
 
        if (*list == NULL) {
8142
 
            xmlTreeErrMemory("realloc ns map item");
8143
 
            return(-1);
8144
 
        }
8145
 
    }
8146
 
    (*list)[2 * (*number)] = oldNs;
8147
 
    (*list)[2 * (*number) +1] = newNs;
8148
 
    (*number)++;
8149
 
    return (0);
8150
 
}
8151
 
 
8152
 
/*
8153
 
* xmlDOMWrapRemoveNode:
8154
 
* @ctxt: a DOM wrapper context
8155
 
* @doc: the doc
8156
 
* @node: the node to be removed.
8157
 
* @options: set of options, unused at the moment
8158
 
*
8159
 
* Unlinks the given node from its owner.
8160
 
* This will substitute ns-references to node->nsDef for
8161
 
* ns-references to doc->oldNs, thus ensuring the removed
8162
 
* branch to be autark wrt ns-references.
8163
 
*
8164
 
* NOTE: This function was not intensively tested.
8165
 
*
8166
 
* Returns 0 on success, 1 if the node is not supported,
8167
 
*         -1 on API and internal errors.
8168
 
*/
8169
 
int
8170
 
xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc,
8171
 
                     xmlNodePtr node, int options ATTRIBUTE_UNUSED)
8172
 
{
8173
 
    xmlNsPtr *list = NULL;
8174
 
    int sizeList, nbList, i, j;
8175
 
    xmlNsPtr ns;
8176
 
 
8177
 
    if ((node == NULL) || (doc == NULL) || (node->doc != doc))
8178
 
        return (-1);
8179
 
 
8180
 
    /* TODO: 0 or -1 ? */
8181
 
    if (node->parent == NULL)
8182
 
        return (0);
8183
 
 
8184
 
    switch (node->type) {
8185
 
        case XML_TEXT_NODE:
8186
 
        case XML_CDATA_SECTION_NODE:
8187
 
        case XML_ENTITY_REF_NODE:
8188
 
        case XML_PI_NODE:
8189
 
        case XML_COMMENT_NODE:
8190
 
            xmlUnlinkNode(node);
8191
 
            return (0);
8192
 
        case XML_ELEMENT_NODE:
8193
 
        case XML_ATTRIBUTE_NODE:
8194
 
            break;
8195
 
        default:
8196
 
            return (1);
8197
 
    }
8198
 
    xmlUnlinkNode(node);
8199
 
    /*
8200
 
    * Save out-of-scope ns-references in doc->oldNs.
8201
 
    */
8202
 
    do {
8203
 
        switch (node->type) {
8204
 
            case XML_ELEMENT_NODE:
8205
 
                if ((ctxt == NULL) && (node->nsDef != NULL)) {
8206
 
                    ns = node->nsDef;
8207
 
                    do {
8208
 
                        if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList,
8209
 
                            &nbList, ns, ns) == -1)
8210
 
                            goto internal_error;
8211
 
                        ns = ns->next;
8212
 
                    } while (ns != NULL);
8213
 
                }
8214
 
                /* No break on purpose. */
8215
 
            case XML_ATTRIBUTE_NODE:
8216
 
                if (node->ns != NULL) {
8217
 
                    /*
8218
 
                    * Find a mapping.
8219
 
                    */
8220
 
                    if (list != NULL) {
8221
 
                        for (i = 0, j = 0; i < nbList; i++, j += 2) {
8222
 
                            if (node->ns == list[j]) {
8223
 
                                node->ns = list[++j];
8224
 
                                goto next_node;
8225
 
                            }
8226
 
                        }
8227
 
                    }
8228
 
                    ns = NULL;
8229
 
                    if (ctxt != NULL) {
8230
 
                        /*
8231
 
                        * User defined.
8232
 
                        */
8233
 
                    } else {
8234
 
                        /*
8235
 
                        * Add to doc's oldNs.
8236
 
                        */
8237
 
                        ns = xmlDOMWrapStoreNs(doc, node->ns->href,
8238
 
                            node->ns->prefix);
8239
 
                        if (ns == NULL)
8240
 
                            goto internal_error;
8241
 
                    }
8242
 
                    if (ns != NULL) {
8243
 
                        /*
8244
 
                        * Add mapping.
8245
 
                        */
8246
 
                        if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList,
8247
 
                            &nbList, node->ns, ns) == -1)
8248
 
                            goto internal_error;
8249
 
                    }
8250
 
                    node->ns = ns;
8251
 
                }
8252
 
                if ((node->type == XML_ELEMENT_NODE) &&
8253
 
                    (node->properties != NULL)) {
8254
 
                    node = (xmlNodePtr) node->properties;
8255
 
                    continue;
8256
 
                }
8257
 
                break;
8258
 
            default:
8259
 
                goto next_sibling;
8260
 
        }
8261
 
next_node:
8262
 
        if ((node->type == XML_ELEMENT_NODE) &&
8263
 
            (node->children != NULL)) {
8264
 
            node = node->children;
8265
 
            continue;
8266
 
        }
8267
 
next_sibling:
8268
 
        if (node == NULL)
8269
 
            break;
8270
 
        if (node->next != NULL)
8271
 
            node = node->next;
8272
 
        else {
8273
 
            node = node->parent;
8274
 
            goto next_sibling;
8275
 
        }
8276
 
    } while (node != NULL);
8277
 
 
8278
 
    if (list != NULL)
8279
 
        xmlFree(list);
8280
 
    return (0);
8281
 
 
8282
 
internal_error:
8283
 
    if (list != NULL)
8284
 
        xmlFree(list);
8285
 
    return (-1);
8286
 
}
8287
 
 
8288
 
/*
8289
 
* xmlSearchNsByNamespaceStrict:
8290
 
* @doc: the document
8291
 
* @node: the start node
8292
 
* @nsName: the searched namespace name
8293
 
* @retNs: the resulting ns-decl
8294
 
* @prefixed: if the found ns-decl must have a prefix (for attributes)
8295
 
*
8296
 
* Dynamically searches for a ns-declaration which matches
8297
 
* the given @nsName in the ancestor-or-self axis of @node.
8298
 
*
8299
 
* Returns 1 if a ns-decl was found, 0 if not and -1 on API
8300
 
*         and internal errors.
8301
 
*/
8302
 
static int
8303
 
xmlSearchNsByNamespaceStrict(xmlDocPtr doc, xmlNodePtr node,
8304
 
                             const xmlChar* nsName,
8305
 
                             xmlNsPtr *retNs, int prefixed)
8306
 
{
8307
 
    xmlNodePtr cur, prev = NULL, out = NULL;
8308
 
    xmlNsPtr ns, prevns;
8309
 
 
8310
 
    if ((doc == NULL) || (nsName == NULL) || (retNs == NULL))
8311
 
        return (-1);
8312
 
    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
8313
 
        return(-1);
8314
 
 
8315
 
    *retNs = NULL;
8316
 
    if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
8317
 
        *retNs = xmlTreeEnsureXMLDecl(doc);
8318
 
        if (*retNs == NULL)
8319
 
            return (-1);
8320
 
        return (1);
8321
 
    }
8322
 
    cur = node;
8323
 
    do {
8324
 
        if (cur->type == XML_ELEMENT_NODE) {
8325
 
            if (cur->nsDef != NULL) {
8326
 
                for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
8327
 
                    if (prefixed && (ns->prefix == NULL))
8328
 
                        continue;
8329
 
                    if (prev != NULL) {
8330
 
                        /*
8331
 
                        * Check the last level of ns-decls for a
8332
 
                        * shadowing prefix.
8333
 
                        */
8334
 
                        prevns = prev->nsDef;
8335
 
                        do {
8336
 
                            if ((prevns->prefix == ns->prefix) ||
8337
 
                                ((prevns->prefix != NULL) &&
8338
 
                                (ns->prefix != NULL) &&
8339
 
                                xmlStrEqual(prevns->prefix, ns->prefix))) {
8340
 
                                /*
8341
 
                                * Shadowed.
8342
 
                                */
8343
 
                                break;
8344
 
                            }
8345
 
                            prevns = prevns->next;
8346
 
                        } while (prevns != NULL);
8347
 
                        if (prevns != NULL)
8348
 
                            continue;
8349
 
                    }
8350
 
                    /*
8351
 
                    * Ns-name comparison.
8352
 
                    */
8353
 
                    if ((nsName == ns->href) ||
8354
 
                        xmlStrEqual(nsName, ns->href)) {
8355
 
                        /*
8356
 
                        * At this point the prefix can only be shadowed,
8357
 
                        * if we are the the (at least) 3rd level of
8358
 
                        * ns-decls.
8359
 
                        */
8360
 
                        if (out) {
8361
 
                            int ret;
8362
 
 
8363
 
                            ret = xmlNsInScope(doc, node, prev, ns->prefix);
8364
 
                            if (ret < 0)
8365
 
                                return (-1);
8366
 
                            /*
8367
 
                            * TODO: Should we try to find a matching ns-name
8368
 
                            * only once? This here keeps on searching.
8369
 
                            * I think we should try further since, there might
8370
 
                            * be an other matching ns-decl with an unshadowed
8371
 
                            * prefix.
8372
 
                            */
8373
 
                            if (! ret)
8374
 
                                continue;
8375
 
                        }
8376
 
                        *retNs = ns;
8377
 
                        return (1);
8378
 
                    }
8379
 
                }
8380
 
                out = prev;
8381
 
                prev = cur;
8382
 
            }
8383
 
        } else if ((cur->type == XML_ENTITY_NODE) ||
8384
 
            (cur->type == XML_ENTITY_DECL))
8385
 
            return (0);
8386
 
        cur = cur->parent;
8387
 
    } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));
8388
 
    return (0);
8389
 
}
8390
 
 
8391
 
/*
8392
 
* xmlSearchNsByPrefixStrict:
8393
 
* @doc: the document
8394
 
* @node: the start node
8395
 
* @prefix: the searched namespace prefix
8396
 
* @retNs: the resulting ns-decl
8397
 
*
8398
 
* Dynamically searches for a ns-declaration which matches
8399
 
* the given @nsName in the ancestor-or-self axis of @node.
8400
 
*
8401
 
* Returns 1 if a ns-decl was found, 0 if not and -1 on API
8402
 
*         and internal errors.
8403
 
*/
8404
 
static int
8405
 
xmlSearchNsByPrefixStrict(xmlDocPtr doc, xmlNodePtr node,
8406
 
                          const xmlChar* prefix,
8407
 
                          xmlNsPtr *retNs)
8408
 
{
8409
 
    xmlNodePtr cur;
8410
 
    xmlNsPtr ns;
8411
 
 
8412
 
    if ((doc == NULL) || (node == NULL) || (node->type == XML_NAMESPACE_DECL))
8413
 
        return(-1);
8414
 
 
8415
 
    if (retNs)
8416
 
        *retNs = NULL;
8417
 
    if (IS_STR_XML(prefix)) {
8418
 
        if (retNs) {
8419
 
            *retNs = xmlTreeEnsureXMLDecl(doc);
8420
 
            if (*retNs == NULL)
8421
 
                return (-1);
8422
 
        }
8423
 
        return (1);
8424
 
    }
8425
 
    cur = node;
8426
 
    do {
8427
 
        if (cur->type == XML_ELEMENT_NODE) {
8428
 
            if (cur->nsDef != NULL) {
8429
 
                ns = cur->nsDef;
8430
 
                do {
8431
 
                    if ((prefix == ns->prefix) ||
8432
 
                        xmlStrEqual(prefix, ns->prefix))
8433
 
                    {
8434
 
                        /*
8435
 
                        * Disabled namespaces, e.g. xmlns:abc="".
8436
 
                        */
8437
 
                        if (ns->href == NULL)
8438
 
                            return(0);
8439
 
                        if (retNs)
8440
 
                            *retNs = ns;
8441
 
                        return (1);
8442
 
                    }
8443
 
                    ns = ns->next;
8444
 
                } while (ns != NULL);
8445
 
            }
8446
 
        } else if ((cur->type == XML_ENTITY_NODE) ||
8447
 
            (cur->type == XML_ENTITY_DECL))
8448
 
            return (0);
8449
 
        cur = cur->parent;
8450
 
    } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));
8451
 
    return (0);
8452
 
}
8453
 
 
8454
 
/*
8455
 
* xmlDOMWrapNSNormDeclareNsForced:
8456
 
* @doc: the doc
8457
 
* @elem: the element-node to declare on
8458
 
* @nsName: the namespace-name of the ns-decl
8459
 
* @prefix: the preferred prefix of the ns-decl
8460
 
* @checkShadow: ensure that the new ns-decl doesn't shadow ancestor ns-decls
8461
 
*
8462
 
* Declares a new namespace on @elem. It tries to use the
8463
 
* given @prefix; if a ns-decl with the given prefix is already existent
8464
 
* on @elem, it will generate an other prefix.
8465
 
*
8466
 
* Returns 1 if a ns-decl was found, 0 if not and -1 on API
8467
 
*         and internal errors.
8468
 
*/
8469
 
static xmlNsPtr
8470
 
xmlDOMWrapNSNormDeclareNsForced(xmlDocPtr doc,
8471
 
                                xmlNodePtr elem,
8472
 
                                const xmlChar *nsName,
8473
 
                                const xmlChar *prefix,
8474
 
                                int checkShadow)
8475
 
{
8476
 
 
8477
 
    xmlNsPtr ret;
8478
 
    char buf[50];
8479
 
    const xmlChar *pref;
8480
 
    int counter = 0;
8481
 
 
8482
 
    if ((doc == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
8483
 
        return(NULL);
8484
 
    /*
8485
 
    * Create a ns-decl on @anchor.
8486
 
    */
8487
 
    pref = prefix;
8488
 
    while (1) {
8489
 
        /*
8490
 
        * Lookup whether the prefix is unused in elem's ns-decls.
8491
 
        */
8492
 
        if ((elem->nsDef != NULL) &&
8493
 
            (xmlTreeNSListLookupByPrefix(elem->nsDef, pref) != NULL))
8494
 
            goto ns_next_prefix;
8495
 
        if (checkShadow && elem->parent &&
8496
 
            ((xmlNodePtr) elem->parent->doc != elem->parent)) {
8497
 
            /*
8498
 
            * Does it shadow ancestor ns-decls?
8499
 
            */
8500
 
            if (xmlSearchNsByPrefixStrict(doc, elem->parent, pref, NULL) == 1)
8501
 
                goto ns_next_prefix;
8502
 
        }
8503
 
        ret = xmlNewNs(NULL, nsName, pref);
8504
 
        if (ret == NULL)
8505
 
            return (NULL);
8506
 
        if (elem->nsDef == NULL)
8507
 
            elem->nsDef = ret;
8508
 
        else {
8509
 
            xmlNsPtr ns2 = elem->nsDef;
8510
 
            while (ns2->next != NULL)
8511
 
                ns2 = ns2->next;
8512
 
            ns2->next = ret;
8513
 
        }
8514
 
        return (ret);
8515
 
ns_next_prefix:
8516
 
        counter++;
8517
 
        if (counter > 1000)
8518
 
            return (NULL);
8519
 
        if (prefix == NULL) {
8520
 
            snprintf((char *) buf, sizeof(buf),
8521
 
                "ns_%d", counter);
8522
 
        } else
8523
 
            snprintf((char *) buf, sizeof(buf),
8524
 
            "%.30s_%d", (char *)prefix, counter);
8525
 
        pref = BAD_CAST buf;
8526
 
    }
8527
 
}
8528
 
 
8529
 
/*
8530
 
* xmlDOMWrapNSNormAquireNormalizedNs:
8531
 
* @doc: the doc
8532
 
* @elem: the element-node to declare namespaces on
8533
 
* @ns: the ns-struct to use for the search
8534
 
* @retNs: the found/created ns-struct
8535
 
* @nsMap: the ns-map
8536
 
* @depth: the current tree depth
8537
 
* @ancestorsOnly: search in ancestor ns-decls only
8538
 
* @prefixed: if the searched ns-decl must have a prefix (for attributes)
8539
 
*
8540
 
* Searches for a matching ns-name in the ns-decls of @nsMap, if not
8541
 
* found it will either declare it on @elem, or store it in doc->oldNs.
8542
 
* If a new ns-decl needs to be declared on @elem, it tries to use the
8543
 
* @ns->prefix for it, if this prefix is already in use on @elem, it will
8544
 
* change the prefix or the new ns-decl.
8545
 
*
8546
 
* Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8547
 
*/
8548
 
static int
8549
 
xmlDOMWrapNSNormAquireNormalizedNs(xmlDocPtr doc,
8550
 
                                   xmlNodePtr elem,
8551
 
                                   xmlNsPtr ns,
8552
 
                                   xmlNsPtr *retNs,
8553
 
                                   xmlNsMapPtr *nsMap,
8554
 
 
8555
 
                                   int depth,
8556
 
                                   int ancestorsOnly,
8557
 
                                   int prefixed)
8558
 
{
8559
 
    xmlNsMapItemPtr mi;
8560
 
 
8561
 
    if ((doc == NULL) || (ns == NULL) || (retNs == NULL) ||
8562
 
        (nsMap == NULL))
8563
 
        return (-1);
8564
 
 
8565
 
    *retNs = NULL;
8566
 
    /*
8567
 
    * Handle XML namespace.
8568
 
    */
8569
 
    if (IS_STR_XML(ns->prefix)) {
8570
 
        /*
8571
 
        * Insert XML namespace mapping.
8572
 
        */
8573
 
        *retNs = xmlTreeEnsureXMLDecl(doc);
8574
 
        if (*retNs == NULL)
8575
 
            return (-1);
8576
 
        return (0);
8577
 
    }
8578
 
    /*
8579
 
    * If the search should be done in ancestors only and no
8580
 
    * @elem (the first ancestor) was specified, then skip the search.
8581
 
    */
8582
 
    if ((XML_NSMAP_NOTEMPTY(*nsMap)) &&
8583
 
        (! (ancestorsOnly && (elem == NULL))))
8584
 
    {
8585
 
        /*
8586
 
        * Try to find an equal ns-name in in-scope ns-decls.
8587
 
        */
8588
 
        XML_NSMAP_FOREACH(*nsMap, mi) {
8589
 
            if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
8590
 
                /*
8591
 
                * ancestorsOnly: This should be turned on to gain speed,
8592
 
                * if one knows that the branch itself was already
8593
 
                * ns-wellformed and no stale references existed.
8594
 
                * I.e. it searches in the ancestor axis only.
8595
 
                */
8596
 
                ((! ancestorsOnly) || (mi->depth == XML_TREE_NSMAP_PARENT)) &&
8597
 
                /* Skip shadowed prefixes. */
8598
 
                (mi->shadowDepth == -1) &&
8599
 
                /* Skip xmlns="" or xmlns:foo="". */
8600
 
                ((mi->newNs->href != NULL) &&
8601
 
                (mi->newNs->href[0] != 0)) &&
8602
 
                /* Ensure a prefix if wanted. */
8603
 
                ((! prefixed) || (mi->newNs->prefix != NULL)) &&
8604
 
                /* Equal ns name */
8605
 
                ((mi->newNs->href == ns->href) ||
8606
 
                xmlStrEqual(mi->newNs->href, ns->href))) {
8607
 
                /* Set the mapping. */
8608
 
                mi->oldNs = ns;
8609
 
                *retNs = mi->newNs;
8610
 
                return (0);
8611
 
            }
8612
 
        }
8613
 
    }
8614
 
    /*
8615
 
    * No luck, the namespace is out of scope or shadowed.
8616
 
    */
8617
 
    if (elem == NULL) {
8618
 
        xmlNsPtr tmpns;
8619
 
 
8620
 
        /*
8621
 
        * Store ns-decls in "oldNs" of the document-node.
8622
 
        */
8623
 
        tmpns = xmlDOMWrapStoreNs(doc, ns->href, ns->prefix);
8624
 
        if (tmpns == NULL)
8625
 
            return (-1);
8626
 
        /*
8627
 
        * Insert mapping.
8628
 
        */
8629
 
        if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns,
8630
 
                tmpns, XML_TREE_NSMAP_DOC) == NULL) {
8631
 
            xmlFreeNs(tmpns);
8632
 
            return (-1);
8633
 
        }
8634
 
        *retNs = tmpns;
8635
 
    } else {
8636
 
        xmlNsPtr tmpns;
8637
 
 
8638
 
        tmpns = xmlDOMWrapNSNormDeclareNsForced(doc, elem, ns->href,
8639
 
            ns->prefix, 0);
8640
 
        if (tmpns == NULL)
8641
 
            return (-1);
8642
 
 
8643
 
        if (*nsMap != NULL) {
8644
 
            /*
8645
 
            * Does it shadow ancestor ns-decls?
8646
 
            */
8647
 
            XML_NSMAP_FOREACH(*nsMap, mi) {
8648
 
                if ((mi->depth < depth) &&
8649
 
                    (mi->shadowDepth == -1) &&
8650
 
                    ((ns->prefix == mi->newNs->prefix) ||
8651
 
                    xmlStrEqual(ns->prefix, mi->newNs->prefix))) {
8652
 
                    /*
8653
 
                    * Shadows.
8654
 
                    */
8655
 
                    mi->shadowDepth = depth;
8656
 
                    break;
8657
 
                }
8658
 
            }
8659
 
        }
8660
 
        if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns, tmpns, depth) == NULL) {
8661
 
            xmlFreeNs(tmpns);
8662
 
            return (-1);
8663
 
        }
8664
 
        *retNs = tmpns;
8665
 
    }
8666
 
    return (0);
8667
 
}
8668
 
 
8669
 
typedef enum {
8670
 
    XML_DOM_RECONNS_REMOVEREDUND = 1<<0
8671
 
} xmlDOMReconcileNSOptions;
8672
 
 
8673
 
/*
8674
 
* xmlDOMWrapReconcileNamespaces:
8675
 
* @ctxt: DOM wrapper context, unused at the moment
8676
 
* @elem: the element-node
8677
 
* @options: option flags
8678
 
*
8679
 
* Ensures that ns-references point to ns-decls hold on element-nodes.
8680
 
* Ensures that the tree is namespace wellformed by creating additional
8681
 
* ns-decls where needed. Note that, since prefixes of already existent
8682
 
* ns-decls can be shadowed by this process, it could break QNames in
8683
 
* attribute values or element content.
8684
 
*
8685
 
* NOTE: This function was not intensively tested.
8686
 
*
8687
 
* Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8688
 
*/
8689
 
 
8690
 
int
8691
 
xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED,
8692
 
                              xmlNodePtr elem,
8693
 
                              int options)
8694
 
{
8695
 
    int depth = -1, adoptns = 0, parnsdone = 0;
8696
 
    xmlNsPtr ns, prevns;
8697
 
    xmlDocPtr doc;
8698
 
    xmlNodePtr cur, curElem = NULL;
8699
 
    xmlNsMapPtr nsMap = NULL;
8700
 
    xmlNsMapItemPtr /* topmi = NULL, */ mi;
8701
 
    /* @ancestorsOnly should be set by an option flag. */
8702
 
    int ancestorsOnly = 0;
8703
 
    int optRemoveRedundantNS =
8704
 
        ((xmlDOMReconcileNSOptions) options & XML_DOM_RECONNS_REMOVEREDUND) ? 1 : 0;
8705
 
    xmlNsPtr *listRedund = NULL;
8706
 
    int sizeRedund = 0, nbRedund = 0, ret, i, j;
8707
 
 
8708
 
    if ((elem == NULL) || (elem->doc == NULL) ||
8709
 
        (elem->type != XML_ELEMENT_NODE))
8710
 
        return (-1);
8711
 
 
8712
 
    doc = elem->doc;
8713
 
    cur = elem;
8714
 
    do {
8715
 
        switch (cur->type) {
8716
 
            case XML_ELEMENT_NODE:
8717
 
                adoptns = 1;
8718
 
                curElem = cur;
8719
 
                depth++;
8720
 
                /*
8721
 
                * Namespace declarations.
8722
 
                */
8723
 
                if (cur->nsDef != NULL) {
8724
 
                    prevns = NULL;
8725
 
                    ns = cur->nsDef;
8726
 
                    while (ns != NULL) {
8727
 
                        if (! parnsdone) {
8728
 
                            if ((elem->parent) &&
8729
 
                                ((xmlNodePtr) elem->parent->doc != elem->parent)) {
8730
 
                                /*
8731
 
                                * Gather ancestor in-scope ns-decls.
8732
 
                                */
8733
 
                                if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
8734
 
                                    elem->parent) == -1)
8735
 
                                    goto internal_error;
8736
 
                            }
8737
 
                            parnsdone = 1;
8738
 
                        }
8739
 
 
8740
 
                        /*
8741
 
                        * Lookup the ns ancestor-axis for equal ns-decls in scope.
8742
 
                        */
8743
 
                        if (optRemoveRedundantNS && XML_NSMAP_NOTEMPTY(nsMap)) {
8744
 
                            XML_NSMAP_FOREACH(nsMap, mi) {
8745
 
                                if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
8746
 
                                    (mi->shadowDepth == -1) &&
8747
 
                                    ((ns->prefix == mi->newNs->prefix) ||
8748
 
                                      xmlStrEqual(ns->prefix, mi->newNs->prefix)) &&
8749
 
                                    ((ns->href == mi->newNs->href) ||
8750
 
                                      xmlStrEqual(ns->href, mi->newNs->href)))
8751
 
                                {
8752
 
                                    /*
8753
 
                                    * A redundant ns-decl was found.
8754
 
                                    * Add it to the list of redundant ns-decls.
8755
 
                                    */
8756
 
                                    if (xmlDOMWrapNSNormAddNsMapItem2(&listRedund,
8757
 
                                        &sizeRedund, &nbRedund, ns, mi->newNs) == -1)
8758
 
                                        goto internal_error;
8759
 
                                    /*
8760
 
                                    * Remove the ns-decl from the element-node.
8761
 
                                    */
8762
 
                                    if (prevns)
8763
 
                                        prevns->next = ns->next;
8764
 
                                    else
8765
 
                                        cur->nsDef = ns->next;
8766
 
                                    goto next_ns_decl;
8767
 
                                }
8768
 
                            }
8769
 
                        }
8770
 
 
8771
 
                        /*
8772
 
                        * Skip ns-references handling if the referenced
8773
 
                        * ns-decl is declared on the same element.
8774
 
                        */
8775
 
                        if ((cur->ns != NULL) && adoptns && (cur->ns == ns))
8776
 
                            adoptns = 0;
8777
 
                        /*
8778
 
                        * Does it shadow any ns-decl?
8779
 
                        */
8780
 
                        if (XML_NSMAP_NOTEMPTY(nsMap)) {
8781
 
                            XML_NSMAP_FOREACH(nsMap, mi) {
8782
 
                                if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
8783
 
                                    (mi->shadowDepth == -1) &&
8784
 
                                    ((ns->prefix == mi->newNs->prefix) ||
8785
 
                                    xmlStrEqual(ns->prefix, mi->newNs->prefix))) {
8786
 
 
8787
 
                                    mi->shadowDepth = depth;
8788
 
                                }
8789
 
                            }
8790
 
                        }
8791
 
                        /*
8792
 
                        * Push mapping.
8793
 
                        */
8794
 
                        if (xmlDOMWrapNsMapAddItem(&nsMap, -1, ns, ns,
8795
 
                            depth) == NULL)
8796
 
                            goto internal_error;
8797
 
 
8798
 
                        prevns = ns;
8799
 
next_ns_decl:
8800
 
                        ns = ns->next;
8801
 
                    }
8802
 
                }
8803
 
                if (! adoptns)
8804
 
                    goto ns_end;
8805
 
                /* No break on purpose. */
8806
 
            case XML_ATTRIBUTE_NODE:
8807
 
                /* No ns, no fun. */
8808
 
                if (cur->ns == NULL)
8809
 
                    goto ns_end;
8810
 
 
8811
 
                if (! parnsdone) {
8812
 
                    if ((elem->parent) &&
8813
 
                        ((xmlNodePtr) elem->parent->doc != elem->parent)) {
8814
 
                        if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
8815
 
                                elem->parent) == -1)
8816
 
                            goto internal_error;
8817
 
                    }
8818
 
                    parnsdone = 1;
8819
 
                }
8820
 
                /*
8821
 
                * Adjust the reference if this was a redundant ns-decl.
8822
 
                */
8823
 
                if (listRedund) {
8824
 
                   for (i = 0, j = 0; i < nbRedund; i++, j += 2) {
8825
 
                       if (cur->ns == listRedund[j]) {
8826
 
                           cur->ns = listRedund[++j];
8827
 
                           break;
8828
 
                       }
8829
 
                   }
8830
 
                }
8831
 
                /*
8832
 
                * Adopt ns-references.
8833
 
                */
8834
 
                if (XML_NSMAP_NOTEMPTY(nsMap)) {
8835
 
                    /*
8836
 
                    * Search for a mapping.
8837
 
                    */
8838
 
                    XML_NSMAP_FOREACH(nsMap, mi) {
8839
 
                        if ((mi->shadowDepth == -1) &&
8840
 
                            (cur->ns == mi->oldNs)) {
8841
 
 
8842
 
                            cur->ns = mi->newNs;
8843
 
                            goto ns_end;
8844
 
                        }
8845
 
                    }
8846
 
                }
8847
 
                /*
8848
 
                * Aquire a normalized ns-decl and add it to the map.
8849
 
                */
8850
 
                if (xmlDOMWrapNSNormAquireNormalizedNs(doc, curElem,
8851
 
                        cur->ns, &ns,
8852
 
                        &nsMap, depth,
8853
 
                        ancestorsOnly,
8854
 
                        (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
8855
 
                    goto internal_error;
8856
 
                cur->ns = ns;
8857
 
 
8858
 
ns_end:
8859
 
                if ((cur->type == XML_ELEMENT_NODE) &&
8860
 
                    (cur->properties != NULL)) {
8861
 
                    /*
8862
 
                    * Process attributes.
8863
 
                    */
8864
 
                    cur = (xmlNodePtr) cur->properties;
8865
 
                    continue;
8866
 
                }
8867
 
                break;
8868
 
            default:
8869
 
                goto next_sibling;
8870
 
        }
8871
 
into_content:
8872
 
        if ((cur->type == XML_ELEMENT_NODE) &&
8873
 
            (cur->children != NULL)) {
8874
 
            /*
8875
 
            * Process content of element-nodes only.
8876
 
            */
8877
 
            cur = cur->children;
8878
 
            continue;
8879
 
        }
8880
 
next_sibling:
8881
 
        if (cur == elem)
8882
 
            break;
8883
 
        if (cur->type == XML_ELEMENT_NODE) {
8884
 
            if (XML_NSMAP_NOTEMPTY(nsMap)) {
8885
 
                /*
8886
 
                * Pop mappings.
8887
 
                */
8888
 
                while ((nsMap->last != NULL) &&
8889
 
                    (nsMap->last->depth >= depth))
8890
 
                {
8891
 
                    XML_NSMAP_POP(nsMap, mi)
8892
 
                }
8893
 
                /*
8894
 
                * Unshadow.
8895
 
                */
8896
 
                XML_NSMAP_FOREACH(nsMap, mi) {
8897
 
                    if (mi->shadowDepth >= depth)
8898
 
                        mi->shadowDepth = -1;
8899
 
                }
8900
 
            }
8901
 
            depth--;
8902
 
        }
8903
 
        if (cur->next != NULL)
8904
 
            cur = cur->next;
8905
 
        else {
8906
 
            if (cur->type == XML_ATTRIBUTE_NODE) {
8907
 
                cur = cur->parent;
8908
 
                goto into_content;
8909
 
            }
8910
 
            cur = cur->parent;
8911
 
            goto next_sibling;
8912
 
        }
8913
 
    } while (cur != NULL);
8914
 
 
8915
 
    ret = 0;
8916
 
    goto exit;
8917
 
internal_error:
8918
 
    ret = -1;
8919
 
exit:
8920
 
    if (listRedund) {
8921
 
        for (i = 0, j = 0; i < nbRedund; i++, j += 2) {
8922
 
            xmlFreeNs(listRedund[j]);
8923
 
        }
8924
 
        xmlFree(listRedund);
8925
 
    }
8926
 
    if (nsMap != NULL)
8927
 
        xmlDOMWrapNsMapFree(nsMap);
8928
 
    return (ret);
8929
 
}
8930
 
 
8931
 
/*
8932
 
* xmlDOMWrapAdoptBranch:
8933
 
* @ctxt: the optional context for custom processing
8934
 
* @sourceDoc: the optional sourceDoc
8935
 
* @node: the element-node to start with
8936
 
* @destDoc: the destination doc for adoption
8937
 
* @destParent: the optional new parent of @node in @destDoc
8938
 
* @options: option flags
8939
 
*
8940
 
* Ensures that ns-references point to @destDoc: either to
8941
 
* elements->nsDef entries if @destParent is given, or to
8942
 
* @destDoc->oldNs otherwise.
8943
 
* If @destParent is given, it ensures that the tree is namespace
8944
 
* wellformed by creating additional ns-decls where needed.
8945
 
* Note that, since prefixes of already existent ns-decls can be
8946
 
* shadowed by this process, it could break QNames in attribute
8947
 
* values or element content.
8948
 
*
8949
 
* NOTE: This function was not intensively tested.
8950
 
*
8951
 
* Returns 0 if succeeded, -1 otherwise and on API/internal errors.
8952
 
*/
8953
 
static int
8954
 
xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,
8955
 
                      xmlDocPtr sourceDoc,
8956
 
                      xmlNodePtr node,
8957
 
                      xmlDocPtr destDoc,
8958
 
                      xmlNodePtr destParent,
8959
 
                      int options ATTRIBUTE_UNUSED)
8960
 
{
8961
 
    int ret = 0;
8962
 
    xmlNodePtr cur, curElem = NULL;
8963
 
    xmlNsMapPtr nsMap = NULL;
8964
 
    xmlNsMapItemPtr mi;
8965
 
    xmlNsPtr ns = NULL;
8966
 
    int depth = -1, adoptStr = 1;
8967
 
    /* gather @parent's ns-decls. */
8968
 
    int parnsdone;
8969
 
    /* @ancestorsOnly should be set per option. */
8970
 
    int ancestorsOnly = 0;
8971
 
 
8972
 
    /*
8973
 
    * Optimize string adoption for equal or none dicts.
8974
 
    */
8975
 
    if ((sourceDoc != NULL) &&
8976
 
        (sourceDoc->dict == destDoc->dict))
8977
 
        adoptStr = 0;
8978
 
    else
8979
 
        adoptStr = 1;
8980
 
 
8981
 
    /*
8982
 
    * Get the ns-map from the context if available.
8983
 
    */
8984
 
    if (ctxt)
8985
 
        nsMap = (xmlNsMapPtr) ctxt->namespaceMap;
8986
 
    /*
8987
 
    * Disable search for ns-decls in the parent-axis of the
8988
 
    * desination element, if:
8989
 
    * 1) there's no destination parent
8990
 
    * 2) custom ns-reference handling is used
8991
 
    */
8992
 
    if ((destParent == NULL) ||
8993
 
        (ctxt && ctxt->getNsForNodeFunc))
8994
 
    {
8995
 
        parnsdone = 1;
8996
 
    } else
8997
 
        parnsdone = 0;
8998
 
 
8999
 
    cur = node;
9000
 
    if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
9001
 
        goto internal_error;
9002
 
 
9003
 
    while (cur != NULL) {
9004
 
        /*
9005
 
        * Paranoid source-doc sanity check.
9006
 
        */
9007
 
        if (cur->doc != sourceDoc) {
9008
 
            /*
9009
 
            * We'll assume XIncluded nodes if the doc differs.
9010
 
            * TODO: Do we need to reconciliate XIncluded nodes?
9011
 
            * This here skips XIncluded nodes and tries to handle
9012
 
            * broken sequences.
9013
 
            */
9014
 
            if (cur->next == NULL)
9015
 
                goto leave_node;
9016
 
            do {
9017
 
                cur = cur->next;
9018
 
                if ((cur->type == XML_XINCLUDE_END) ||
9019
 
                    (cur->doc == node->doc))
9020
 
                    break;
9021
 
            } while (cur->next != NULL);
9022
 
 
9023
 
            if (cur->doc != node->doc)
9024
 
                goto leave_node;
9025
 
        }
9026
 
        cur->doc = destDoc;
9027
 
        switch (cur->type) {
9028
 
            case XML_XINCLUDE_START:
9029
 
            case XML_XINCLUDE_END:
9030
 
                /*
9031
 
                * TODO
9032
 
                */
9033
 
                return (-1);
9034
 
            case XML_ELEMENT_NODE:
9035
 
                curElem = cur;
9036
 
                depth++;
9037
 
                /*
9038
 
                * Namespace declarations.
9039
 
                * - ns->href and ns->prefix are never in the dict, so
9040
 
                *   we need not move the values over to the destination dict.
9041
 
                * - Note that for custom handling of ns-references,
9042
 
                *   the ns-decls need not be stored in the ns-map,
9043
 
                *   since they won't be referenced by node->ns.
9044
 
                */
9045
 
                if ((cur->nsDef) &&
9046
 
                    ((ctxt == NULL) || (ctxt->getNsForNodeFunc == NULL)))
9047
 
                {
9048
 
                    if (! parnsdone) {
9049
 
                        /*
9050
 
                        * Gather @parent's in-scope ns-decls.
9051
 
                        */
9052
 
                        if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
9053
 
                            destParent) == -1)
9054
 
                            goto internal_error;
9055
 
                        parnsdone = 1;
9056
 
                    }
9057
 
                    for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
9058
 
                        /*
9059
 
                        * NOTE: ns->prefix and ns->href are never in the dict.
9060
 
                        * XML_TREE_ADOPT_STR(ns->prefix)
9061
 
                        * XML_TREE_ADOPT_STR(ns->href)
9062
 
                        */
9063
 
                        /*
9064
 
                        * Does it shadow any ns-decl?
9065
 
                        */
9066
 
                        if (XML_NSMAP_NOTEMPTY(nsMap)) {
9067
 
                            XML_NSMAP_FOREACH(nsMap, mi) {
9068
 
                                if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
9069
 
                                    (mi->shadowDepth == -1) &&
9070
 
                                    ((ns->prefix == mi->newNs->prefix) ||
9071
 
                                    xmlStrEqual(ns->prefix,
9072
 
                                    mi->newNs->prefix))) {
9073
 
 
9074
 
                                    mi->shadowDepth = depth;
9075
 
                                }
9076
 
                            }
9077
 
                        }
9078
 
                        /*
9079
 
                        * Push mapping.
9080
 
                        */
9081
 
                        if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
9082
 
                            ns, ns, depth) == NULL)
9083
 
                            goto internal_error;
9084
 
                    }
9085
 
                }
9086
 
                /* No break on purpose. */
9087
 
            case XML_ATTRIBUTE_NODE:
9088
 
                /* No namespace, no fun. */
9089
 
                if (cur->ns == NULL)
9090
 
                    goto ns_end;
9091
 
 
9092
 
                if (! parnsdone) {
9093
 
                    if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
9094
 
                        destParent) == -1)
9095
 
                        goto internal_error;
9096
 
                    parnsdone = 1;
9097
 
                }
9098
 
                /*
9099
 
                * Adopt ns-references.
9100
 
                */
9101
 
                if (XML_NSMAP_NOTEMPTY(nsMap)) {
9102
 
                    /*
9103
 
                    * Search for a mapping.
9104
 
                    */
9105
 
                    XML_NSMAP_FOREACH(nsMap, mi) {
9106
 
                        if ((mi->shadowDepth == -1) &&
9107
 
                            (cur->ns == mi->oldNs)) {
9108
 
 
9109
 
                            cur->ns = mi->newNs;
9110
 
                            goto ns_end;
9111
 
                        }
9112
 
                    }
9113
 
                }
9114
 
                /*
9115
 
                * No matching namespace in scope. We need a new one.
9116
 
                */
9117
 
                if ((ctxt) && (ctxt->getNsForNodeFunc)) {
9118
 
                    /*
9119
 
                    * User-defined behaviour.
9120
 
                    */
9121
 
                    ns = ctxt->getNsForNodeFunc(ctxt, cur,
9122
 
                        cur->ns->href, cur->ns->prefix);
9123
 
                    /*
9124
 
                    * Insert mapping if ns is available; it's the users fault
9125
 
                    * if not.
9126
 
                    */
9127
 
                    if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
9128
 
                            cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)
9129
 
                        goto internal_error;
9130
 
                    cur->ns = ns;
9131
 
                } else {
9132
 
                    /*
9133
 
                    * Aquire a normalized ns-decl and add it to the map.
9134
 
                    */
9135
 
                    if (xmlDOMWrapNSNormAquireNormalizedNs(destDoc,
9136
 
                        /* ns-decls on curElem or on destDoc->oldNs */
9137
 
                        destParent ? curElem : NULL,
9138
 
                        cur->ns, &ns,
9139
 
                        &nsMap, depth,
9140
 
                        ancestorsOnly,
9141
 
                        /* ns-decls must be prefixed for attributes. */
9142
 
                        (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
9143
 
                        goto internal_error;
9144
 
                    cur->ns = ns;
9145
 
                }
9146
 
ns_end:
9147
 
                /*
9148
 
                * Further node properties.
9149
 
                * TODO: Is this all?
9150
 
                */
9151
 
                XML_TREE_ADOPT_STR(cur->name)
9152
 
                if (cur->type == XML_ELEMENT_NODE) {
9153
 
                    cur->psvi = NULL;
9154
 
                    cur->line = 0;
9155
 
                    cur->extra = 0;
9156
 
                    /*
9157
 
                    * Walk attributes.
9158
 
                    */
9159
 
                    if (cur->properties != NULL) {
9160
 
                        /*
9161
 
                        * Process first attribute node.
9162
 
                        */
9163
 
                        cur = (xmlNodePtr) cur->properties;
9164
 
                        continue;
9165
 
                    }
9166
 
                } else {
9167
 
                    /*
9168
 
                    * Attributes.
9169
 
                    */
9170
 
                    if ((sourceDoc != NULL) &&
9171
 
                        (((xmlAttrPtr) cur)->atype == XML_ATTRIBUTE_ID))
9172
 
                    {
9173
 
                        xmlRemoveID(sourceDoc, (xmlAttrPtr) cur);
9174
 
                    }
9175
 
                    ((xmlAttrPtr) cur)->atype = 0;
9176
 
                    ((xmlAttrPtr) cur)->psvi = NULL;
9177
 
                }
9178
 
                break;
9179
 
            case XML_TEXT_NODE:
9180
 
            case XML_CDATA_SECTION_NODE:
9181
 
                /*
9182
 
                * This puts the content in the dest dict, only if
9183
 
                * it was previously in the source dict.
9184
 
                */
9185
 
                XML_TREE_ADOPT_STR_2(cur->content)
9186
 
                goto leave_node;
9187
 
            case XML_ENTITY_REF_NODE:
9188
 
                /*
9189
 
                * Remove reference to the entitity-node.
9190
 
                */
9191
 
                cur->content = NULL;
9192
 
                cur->children = NULL;
9193
 
                cur->last = NULL;
9194
 
                if ((destDoc->intSubset) || (destDoc->extSubset)) {
9195
 
                    xmlEntityPtr ent;
9196
 
                    /*
9197
 
                    * Assign new entity-node if available.
9198
 
                    */
9199
 
                    ent = xmlGetDocEntity(destDoc, cur->name);
9200
 
                    if (ent != NULL) {
9201
 
                        cur->content = ent->content;
9202
 
                        cur->children = (xmlNodePtr) ent;
9203
 
                        cur->last = (xmlNodePtr) ent;
9204
 
                    }
9205
 
                }
9206
 
                goto leave_node;
9207
 
            case XML_PI_NODE:
9208
 
                XML_TREE_ADOPT_STR(cur->name)
9209
 
                XML_TREE_ADOPT_STR_2(cur->content)
9210
 
                break;
9211
 
            case XML_COMMENT_NODE:
9212
 
                break;
9213
 
            default:
9214
 
                goto internal_error;
9215
 
        }
9216
 
        /*
9217
 
        * Walk the tree.
9218
 
        */
9219
 
        if (cur->children != NULL) {
9220
 
            cur = cur->children;
9221
 
            continue;
9222
 
        }
9223
 
 
9224
 
leave_node:
9225
 
        if (cur == node)
9226
 
            break;
9227
 
        if ((cur->type == XML_ELEMENT_NODE) ||
9228
 
            (cur->type == XML_XINCLUDE_START) ||
9229
 
            (cur->type == XML_XINCLUDE_END))
9230
 
        {
9231
 
            /*
9232
 
            * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
9233
 
            */
9234
 
            if (XML_NSMAP_NOTEMPTY(nsMap)) {
9235
 
                /*
9236
 
                * Pop mappings.
9237
 
                */
9238
 
                while ((nsMap->last != NULL) &&
9239
 
                    (nsMap->last->depth >= depth))
9240
 
                {
9241
 
                    XML_NSMAP_POP(nsMap, mi)
9242
 
                }
9243
 
                /*
9244
 
                * Unshadow.
9245
 
                */
9246
 
                XML_NSMAP_FOREACH(nsMap, mi) {
9247
 
                    if (mi->shadowDepth >= depth)
9248
 
                        mi->shadowDepth = -1;
9249
 
                }
9250
 
            }
9251
 
            depth--;
9252
 
        }
9253
 
        if (cur->next != NULL)
9254
 
            cur = cur->next;
9255
 
        else if ((cur->type == XML_ATTRIBUTE_NODE) &&
9256
 
            (cur->parent->children != NULL))
9257
 
        {
9258
 
            cur = cur->parent->children;
9259
 
        } else {
9260
 
            cur = cur->parent;
9261
 
            goto leave_node;
9262
 
        }
9263
 
    }
9264
 
 
9265
 
    goto exit;
9266
 
 
9267
 
internal_error:
9268
 
    ret = -1;
9269
 
 
9270
 
exit:
9271
 
    /*
9272
 
    * Cleanup.
9273
 
    */
9274
 
    if (nsMap != NULL) {
9275
 
        if ((ctxt) && (ctxt->namespaceMap == nsMap)) {
9276
 
            /*
9277
 
            * Just cleanup the map but don't free.
9278
 
            */
9279
 
            if (nsMap->first) {
9280
 
                if (nsMap->pool)
9281
 
                    nsMap->last->next = nsMap->pool;
9282
 
                nsMap->pool = nsMap->first;
9283
 
                nsMap->first = NULL;
9284
 
            }
9285
 
        } else
9286
 
            xmlDOMWrapNsMapFree(nsMap);
9287
 
    }
9288
 
    return(ret);
9289
 
}
9290
 
 
9291
 
/*
9292
 
* xmlDOMWrapCloneNode:
9293
 
* @ctxt: the optional context for custom processing
9294
 
* @sourceDoc: the optional sourceDoc
9295
 
* @node: the node to start with
9296
 
* @resNode: the clone of the given @node
9297
 
* @destDoc: the destination doc
9298
 
* @destParent: the optional new parent of @node in @destDoc
9299
 
* @deep: descend into child if set
9300
 
* @options: option flags
9301
 
*
9302
 
* References of out-of scope ns-decls are remapped to point to @destDoc:
9303
 
* 1) If @destParent is given, then nsDef entries on element-nodes are used
9304
 
* 2) If *no* @destParent is given, then @destDoc->oldNs entries are used.
9305
 
*    This is the case when you don't know already where the cloned branch
9306
 
*    will be added to.
9307
 
*
9308
 
* If @destParent is given, it ensures that the tree is namespace
9309
 
* wellformed by creating additional ns-decls where needed.
9310
 
* Note that, since prefixes of already existent ns-decls can be
9311
 
* shadowed by this process, it could break QNames in attribute
9312
 
* values or element content.
9313
 
* TODO:
9314
 
*   1) What to do with XInclude? Currently this returns an error for XInclude.
9315
 
*
9316
 
* Returns 0 if the operation succeeded,
9317
 
*         1 if a node of unsupported (or not yet supported) type was given,
9318
 
*         -1 on API/internal errors.
9319
 
*/
9320
 
 
9321
 
int
9322
 
xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,
9323
 
                      xmlDocPtr sourceDoc,
9324
 
                      xmlNodePtr node,
9325
 
                      xmlNodePtr *resNode,
9326
 
                      xmlDocPtr destDoc,
9327
 
                      xmlNodePtr destParent,
9328
 
                      int deep,
9329
 
                      int options ATTRIBUTE_UNUSED)
9330
 
{
9331
 
    int ret = 0;
9332
 
    xmlNodePtr cur, curElem = NULL;
9333
 
    xmlNsMapPtr nsMap = NULL;
9334
 
    xmlNsMapItemPtr mi;
9335
 
    xmlNsPtr ns;
9336
 
    int depth = -1;
9337
 
    /* int adoptStr = 1; */
9338
 
    /* gather @parent's ns-decls. */
9339
 
    int parnsdone = 0;
9340
 
    /*
9341
 
    * @ancestorsOnly:
9342
 
    * TODO: @ancestorsOnly should be set per option.
9343
 
    *
9344
 
    */
9345
 
    int ancestorsOnly = 0;
9346
 
    xmlNodePtr resultClone = NULL, clone = NULL, parentClone = NULL, prevClone = NULL;
9347
 
    xmlNsPtr cloneNs = NULL, *cloneNsDefSlot = NULL;
9348
 
    xmlDictPtr dict; /* The destination dict */
9349
 
 
9350
 
    if ((node == NULL) || (resNode == NULL) || (destDoc == NULL))
9351
 
        return(-1);
9352
 
    /*
9353
 
    * TODO: Initially we support only element-nodes.
9354
 
    */
9355
 
    if (node->type != XML_ELEMENT_NODE)
9356
 
        return(1);
9357
 
    /*
9358
 
    * Check node->doc sanity.
9359
 
    */
9360
 
    if ((node->doc != NULL) && (sourceDoc != NULL) &&
9361
 
        (node->doc != sourceDoc)) {
9362
 
        /*
9363
 
        * Might be an XIncluded node.
9364
 
        */
9365
 
        return (-1);
9366
 
    }
9367
 
    if (sourceDoc == NULL)
9368
 
        sourceDoc = node->doc;
9369
 
    if (sourceDoc == NULL)
9370
 
        return (-1);
9371
 
 
9372
 
    dict = destDoc->dict;
9373
 
    /*
9374
 
    * Reuse the namespace map of the context.
9375
 
    */
9376
 
    if (ctxt)
9377
 
        nsMap = (xmlNsMapPtr) ctxt->namespaceMap;
9378
 
 
9379
 
    *resNode = NULL;
9380
 
 
9381
 
    cur = node;
9382
 
    if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
9383
 
        return(-1);
9384
 
 
9385
 
    while (cur != NULL) {
9386
 
        if (cur->doc != sourceDoc) {
9387
 
            /*
9388
 
            * We'll assume XIncluded nodes if the doc differs.
9389
 
            * TODO: Do we need to reconciliate XIncluded nodes?
9390
 
            * TODO: This here returns -1 in this case.
9391
 
            */
9392
 
            goto internal_error;
9393
 
        }
9394
 
        /*
9395
 
        * Create a new node.
9396
 
        */
9397
 
        switch (cur->type) {
9398
 
            case XML_XINCLUDE_START:
9399
 
            case XML_XINCLUDE_END:
9400
 
                /*
9401
 
                * TODO: What to do with XInclude?
9402
 
                */
9403
 
                goto internal_error;
9404
 
                break;
9405
 
            case XML_ELEMENT_NODE:
9406
 
            case XML_TEXT_NODE:
9407
 
            case XML_CDATA_SECTION_NODE:
9408
 
            case XML_COMMENT_NODE:
9409
 
            case XML_PI_NODE:
9410
 
            case XML_DOCUMENT_FRAG_NODE:
9411
 
            case XML_ENTITY_REF_NODE:
9412
 
            case XML_ENTITY_NODE:
9413
 
                /*
9414
 
                * Nodes of xmlNode structure.
9415
 
                */
9416
 
                clone = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
9417
 
                if (clone == NULL) {
9418
 
                    xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node");
9419
 
                    goto internal_error;
9420
 
                }
9421
 
                memset(clone, 0, sizeof(xmlNode));
9422
 
                /*
9423
 
                * Set hierachical links.
9424
 
                */
9425
 
                if (resultClone != NULL) {
9426
 
                    clone->parent = parentClone;
9427
 
                    if (prevClone) {
9428
 
                        prevClone->next = clone;
9429
 
                        clone->prev = prevClone;
9430
 
                    } else
9431
 
                        parentClone->children = clone;
9432
 
                } else
9433
 
                    resultClone = clone;
9434
 
 
9435
 
                break;
9436
 
            case XML_ATTRIBUTE_NODE:
9437
 
                /*
9438
 
                * Attributes (xmlAttr).
9439
 
                */
9440
 
                clone = (xmlNodePtr) xmlMalloc(sizeof(xmlAttr));
9441
 
                if (clone == NULL) {
9442
 
                    xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node");
9443
 
                    goto internal_error;
9444
 
                }
9445
 
                memset(clone, 0, sizeof(xmlAttr));
9446
 
                /*
9447
 
                * Set hierachical links.
9448
 
                * TODO: Change this to add to the end of attributes.
9449
 
                */
9450
 
                if (resultClone != NULL) {
9451
 
                    clone->parent = parentClone;
9452
 
                    if (prevClone) {
9453
 
                        prevClone->next = clone;
9454
 
                        clone->prev = prevClone;
9455
 
                    } else
9456
 
                        parentClone->properties = (xmlAttrPtr) clone;
9457
 
                } else
9458
 
                    resultClone = clone;
9459
 
                break;
9460
 
            default:
9461
 
                /*
9462
 
                * TODO QUESTION: Any other nodes expected?
9463
 
                */
9464
 
                goto internal_error;
9465
 
        }
9466
 
 
9467
 
        clone->type = cur->type;
9468
 
        clone->doc = destDoc;
9469
 
 
9470
 
        /*
9471
 
        * Clone the name of the node if any.
9472
 
        */
9473
 
        if (cur->name == xmlStringText)
9474
 
            clone->name = xmlStringText;
9475
 
        else if (cur->name == xmlStringTextNoenc)
9476
 
            /*
9477
 
            * NOTE: Although xmlStringTextNoenc is never assigned to a node
9478
 
            *   in tree.c, it might be set in Libxslt via
9479
 
            *   "xsl:disable-output-escaping".
9480
 
            */
9481
 
            clone->name = xmlStringTextNoenc;
9482
 
        else if (cur->name == xmlStringComment)
9483
 
            clone->name = xmlStringComment;
9484
 
        else if (cur->name != NULL) {
9485
 
            DICT_CONST_COPY(cur->name, clone->name);
9486
 
        }
9487
 
 
9488
 
        switch (cur->type) {
9489
 
            case XML_XINCLUDE_START:
9490
 
            case XML_XINCLUDE_END:
9491
 
                /*
9492
 
                * TODO
9493
 
                */
9494
 
                return (-1);
9495
 
            case XML_ELEMENT_NODE:
9496
 
                curElem = cur;
9497
 
                depth++;
9498
 
                /*
9499
 
                * Namespace declarations.
9500
 
                */
9501
 
                if (cur->nsDef != NULL) {
9502
 
                    if (! parnsdone) {
9503
 
                        if (destParent && (ctxt == NULL)) {
9504
 
                            /*
9505
 
                            * Gather @parent's in-scope ns-decls.
9506
 
                            */
9507
 
                            if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,
9508
 
                                destParent) == -1)
9509
 
                                goto internal_error;
9510
 
                        }
9511
 
                        parnsdone = 1;
9512
 
                    }
9513
 
                    /*
9514
 
                    * Clone namespace declarations.
9515
 
                    */
9516
 
                    cloneNsDefSlot = &(clone->nsDef);
9517
 
                    for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
9518
 
                        /*
9519
 
                        * Create a new xmlNs.
9520
 
                        */
9521
 
                        cloneNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
9522
 
                        if (cloneNs == NULL) {
9523
 
                            xmlTreeErrMemory("xmlDOMWrapCloneNode(): "
9524
 
                                "allocating namespace");
9525
 
                            return(-1);
9526
 
                        }
9527
 
                        memset(cloneNs, 0, sizeof(xmlNs));
9528
 
                        cloneNs->type = XML_LOCAL_NAMESPACE;
9529
 
 
9530
 
                        if (ns->href != NULL)
9531
 
                            cloneNs->href = xmlStrdup(ns->href);
9532
 
                        if (ns->prefix != NULL)
9533
 
                            cloneNs->prefix = xmlStrdup(ns->prefix);
9534
 
 
9535
 
                        *cloneNsDefSlot = cloneNs;
9536
 
                        cloneNsDefSlot = &(cloneNs->next);
9537
 
 
9538
 
                        /*
9539
 
                        * Note that for custom handling of ns-references,
9540
 
                        * the ns-decls need not be stored in the ns-map,
9541
 
                        * since they won't be referenced by node->ns.
9542
 
                        */
9543
 
                        if ((ctxt == NULL) ||
9544
 
                            (ctxt->getNsForNodeFunc == NULL))
9545
 
                        {
9546
 
                            /*
9547
 
                            * Does it shadow any ns-decl?
9548
 
                            */
9549
 
                            if (XML_NSMAP_NOTEMPTY(nsMap)) {
9550
 
                                XML_NSMAP_FOREACH(nsMap, mi) {
9551
 
                                    if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&
9552
 
                                        (mi->shadowDepth == -1) &&
9553
 
                                        ((ns->prefix == mi->newNs->prefix) ||
9554
 
                                        xmlStrEqual(ns->prefix,
9555
 
                                        mi->newNs->prefix))) {
9556
 
                                        /*
9557
 
                                        * Mark as shadowed at the current
9558
 
                                        * depth.
9559
 
                                        */
9560
 
                                        mi->shadowDepth = depth;
9561
 
                                    }
9562
 
                                }
9563
 
                            }
9564
 
                            /*
9565
 
                            * Push mapping.
9566
 
                            */
9567
 
                            if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
9568
 
                                ns, cloneNs, depth) == NULL)
9569
 
                                goto internal_error;
9570
 
                        }
9571
 
                    }
9572
 
                }
9573
 
                /* cur->ns will be processed further down. */
9574
 
                break;
9575
 
            case XML_ATTRIBUTE_NODE:
9576
 
                /* IDs will be processed further down. */
9577
 
                /* cur->ns will be processed further down. */
9578
 
                break;
9579
 
            case XML_TEXT_NODE:
9580
 
            case XML_CDATA_SECTION_NODE:
9581
 
                /*
9582
 
                * Note that this will also cover the values of attributes.
9583
 
                */
9584
 
                DICT_COPY(cur->content, clone->content);
9585
 
                goto leave_node;
9586
 
            case XML_ENTITY_NODE:
9587
 
                /* TODO: What to do here? */
9588
 
                goto leave_node;
9589
 
            case XML_ENTITY_REF_NODE:
9590
 
                if (sourceDoc != destDoc) {
9591
 
                    if ((destDoc->intSubset) || (destDoc->extSubset)) {
9592
 
                        xmlEntityPtr ent;
9593
 
                        /*
9594
 
                        * Different doc: Assign new entity-node if available.
9595
 
                        */
9596
 
                        ent = xmlGetDocEntity(destDoc, cur->name);
9597
 
                        if (ent != NULL) {
9598
 
                            clone->content = ent->content;
9599
 
                            clone->children = (xmlNodePtr) ent;
9600
 
                            clone->last = (xmlNodePtr) ent;
9601
 
                        }
9602
 
                    }
9603
 
                } else {
9604
 
                    /*
9605
 
                    * Same doc: Use the current node's entity declaration
9606
 
                    * and value.
9607
 
                    */
9608
 
                    clone->content = cur->content;
9609
 
                    clone->children = cur->children;
9610
 
                    clone->last = cur->last;
9611
 
                }
9612
 
                goto leave_node;
9613
 
            case XML_PI_NODE:
9614
 
                DICT_COPY(cur->content, clone->content);
9615
 
                goto leave_node;
9616
 
            case XML_COMMENT_NODE:
9617
 
                DICT_COPY(cur->content, clone->content);
9618
 
                goto leave_node;
9619
 
            default:
9620
 
                goto internal_error;
9621
 
        }
9622
 
 
9623
 
        if (cur->ns == NULL)
9624
 
            goto end_ns_reference;
9625
 
 
9626
 
/* handle_ns_reference: */
9627
 
        /*
9628
 
        ** The following will take care of references to ns-decls ********
9629
 
        ** and is intended only for element- and attribute-nodes.
9630
 
        **
9631
 
        */
9632
 
        if (! parnsdone) {
9633
 
            if (destParent && (ctxt == NULL)) {
9634
 
                if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, destParent) == -1)
9635
 
                    goto internal_error;
9636
 
            }
9637
 
            parnsdone = 1;
9638
 
        }
9639
 
        /*
9640
 
        * Adopt ns-references.
9641
 
        */
9642
 
        if (XML_NSMAP_NOTEMPTY(nsMap)) {
9643
 
            /*
9644
 
            * Search for a mapping.
9645
 
            */
9646
 
            XML_NSMAP_FOREACH(nsMap, mi) {
9647
 
                if ((mi->shadowDepth == -1) &&
9648
 
                    (cur->ns == mi->oldNs)) {
9649
 
                    /*
9650
 
                    * This is the nice case: a mapping was found.
9651
 
                    */
9652
 
                    clone->ns = mi->newNs;
9653
 
                    goto end_ns_reference;
9654
 
                }
9655
 
            }
9656
 
        }
9657
 
        /*
9658
 
        * No matching namespace in scope. We need a new one.
9659
 
        */
9660
 
        if ((ctxt != NULL) && (ctxt->getNsForNodeFunc != NULL)) {
9661
 
            /*
9662
 
            * User-defined behaviour.
9663
 
            */
9664
 
            ns = ctxt->getNsForNodeFunc(ctxt, cur,
9665
 
                cur->ns->href, cur->ns->prefix);
9666
 
            /*
9667
 
            * Add user's mapping.
9668
 
            */
9669
 
            if (xmlDOMWrapNsMapAddItem(&nsMap, -1,
9670
 
                cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)
9671
 
                goto internal_error;
9672
 
            clone->ns = ns;
9673
 
        } else {
9674
 
            /*
9675
 
            * Aquire a normalized ns-decl and add it to the map.
9676
 
            */
9677
 
            if (xmlDOMWrapNSNormAquireNormalizedNs(destDoc,
9678
 
                /* ns-decls on curElem or on destDoc->oldNs */
9679
 
                destParent ? curElem : NULL,
9680
 
                cur->ns, &ns,
9681
 
                &nsMap, depth,
9682
 
                /* if we need to search only in the ancestor-axis */
9683
 
                ancestorsOnly,
9684
 
                /* ns-decls must be prefixed for attributes. */
9685
 
                (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)
9686
 
                goto internal_error;
9687
 
            clone->ns = ns;
9688
 
        }
9689
 
 
9690
 
end_ns_reference:
9691
 
 
9692
 
        /*
9693
 
        * Some post-processing.
9694
 
        *
9695
 
        * Handle ID attributes.
9696
 
        */
9697
 
        if ((clone->type == XML_ATTRIBUTE_NODE) &&
9698
 
            (clone->parent != NULL))
9699
 
        {
9700
 
            if (xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone)) {
9701
 
 
9702
 
                xmlChar *idVal;
9703
 
 
9704
 
                idVal = xmlNodeListGetString(cur->doc, cur->children, 1);
9705
 
                if (idVal != NULL) {
9706
 
                    if (xmlAddID(NULL, destDoc, idVal, (xmlAttrPtr) cur) == NULL) {
9707
 
                        /* TODO: error message. */
9708
 
                        xmlFree(idVal);
9709
 
                        goto internal_error;
9710
 
                    }
9711
 
                    xmlFree(idVal);
9712
 
                }
9713
 
            }
9714
 
        }
9715
 
        /*
9716
 
        **
9717
 
        ** The following will traverse the tree **************************
9718
 
        **
9719
 
        *
9720
 
        * Walk the element's attributes before descending into child-nodes.
9721
 
        */
9722
 
        if ((cur->type == XML_ELEMENT_NODE) && (cur->properties != NULL)) {
9723
 
            prevClone = NULL;
9724
 
            parentClone = clone;
9725
 
            cur = (xmlNodePtr) cur->properties;
9726
 
            continue;
9727
 
        }
9728
 
into_content:
9729
 
        /*
9730
 
        * Descend into child-nodes.
9731
 
        */
9732
 
        if (cur->children != NULL) {
9733
 
            if (deep || (cur->type == XML_ATTRIBUTE_NODE)) {
9734
 
                prevClone = NULL;
9735
 
                parentClone = clone;
9736
 
                cur = cur->children;
9737
 
                continue;
9738
 
            }
9739
 
        }
9740
 
 
9741
 
leave_node:
9742
 
        /*
9743
 
        * At this point we are done with the node, its content
9744
 
        * and an element-nodes's attribute-nodes.
9745
 
        */
9746
 
        if (cur == node)
9747
 
            break;
9748
 
        if ((cur->type == XML_ELEMENT_NODE) ||
9749
 
            (cur->type == XML_XINCLUDE_START) ||
9750
 
            (cur->type == XML_XINCLUDE_END)) {
9751
 
            /*
9752
 
            * TODO: Do we expect nsDefs on XML_XINCLUDE_START?
9753
 
            */
9754
 
            if (XML_NSMAP_NOTEMPTY(nsMap)) {
9755
 
                /*
9756
 
                * Pop mappings.
9757
 
                */
9758
 
                while ((nsMap->last != NULL) &&
9759
 
                    (nsMap->last->depth >= depth))
9760
 
                {
9761
 
                    XML_NSMAP_POP(nsMap, mi)
9762
 
                }
9763
 
                /*
9764
 
                * Unshadow.
9765
 
                */
9766
 
                XML_NSMAP_FOREACH(nsMap, mi) {
9767
 
                    if (mi->shadowDepth >= depth)
9768
 
                        mi->shadowDepth = -1;
9769
 
                }
9770
 
            }
9771
 
            depth--;
9772
 
        }
9773
 
        if (cur->next != NULL) {
9774
 
            prevClone = clone;
9775
 
            cur = cur->next;
9776
 
        } else if (cur->type != XML_ATTRIBUTE_NODE) {
9777
 
            /*
9778
 
            * Set clone->last.
9779
 
            */
9780
 
            if (clone->parent != NULL)
9781
 
                clone->parent->last = clone;
9782
 
            clone = clone->parent;
9783
 
            if (clone != NULL)
9784
 
                parentClone = clone->parent;
9785
 
            /*
9786
 
            * Process parent --> next;
9787
 
            */
9788
 
            cur = cur->parent;
9789
 
            goto leave_node;
9790
 
        } else {
9791
 
            /* This is for attributes only. */
9792
 
            clone = clone->parent;
9793
 
            parentClone = clone->parent;
9794
 
            /*
9795
 
            * Process parent-element --> children.
9796
 
            */
9797
 
            cur = cur->parent;
9798
 
            goto into_content;
9799
 
        }
9800
 
    }
9801
 
    goto exit;
9802
 
 
9803
 
internal_error:
9804
 
    ret = -1;
9805
 
 
9806
 
exit:
9807
 
    /*
9808
 
    * Cleanup.
9809
 
    */
9810
 
    if (nsMap != NULL) {
9811
 
        if ((ctxt) && (ctxt->namespaceMap == nsMap)) {
9812
 
            /*
9813
 
            * Just cleanup the map but don't free.
9814
 
            */
9815
 
            if (nsMap->first) {
9816
 
                if (nsMap->pool)
9817
 
                    nsMap->last->next = nsMap->pool;
9818
 
                nsMap->pool = nsMap->first;
9819
 
                nsMap->first = NULL;
9820
 
            }
9821
 
        } else
9822
 
            xmlDOMWrapNsMapFree(nsMap);
9823
 
    }
9824
 
    /*
9825
 
    * TODO: Should we try a cleanup of the cloned node in case of a
9826
 
    * fatal error?
9827
 
    */
9828
 
    *resNode = resultClone;
9829
 
    return (ret);
9830
 
}
9831
 
 
9832
 
/*
9833
 
* xmlDOMWrapAdoptAttr:
9834
 
* @ctxt: the optional context for custom processing
9835
 
* @sourceDoc: the optional source document of attr
9836
 
* @attr: the attribute-node to be adopted
9837
 
* @destDoc: the destination doc for adoption
9838
 
* @destParent: the optional new parent of @attr in @destDoc
9839
 
* @options: option flags
9840
 
*
9841
 
* @attr is adopted by @destDoc.
9842
 
* Ensures that ns-references point to @destDoc: either to
9843
 
* elements->nsDef entries if @destParent is given, or to
9844
 
* @destDoc->oldNs otherwise.
9845
 
*
9846
 
* Returns 0 if succeeded, -1 otherwise and on API/internal errors.
9847
 
*/
9848
 
static int
9849
 
xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt,
9850
 
                    xmlDocPtr sourceDoc,
9851
 
                    xmlAttrPtr attr,
9852
 
                    xmlDocPtr destDoc,
9853
 
                    xmlNodePtr destParent,
9854
 
                    int options ATTRIBUTE_UNUSED)
9855
 
{
9856
 
    xmlNodePtr cur;
9857
 
    int adoptStr = 1;
9858
 
 
9859
 
    if ((attr == NULL) || (destDoc == NULL))
9860
 
        return (-1);
9861
 
 
9862
 
    attr->doc = destDoc;
9863
 
    if (attr->ns != NULL) {
9864
 
        xmlNsPtr ns = NULL;
9865
 
 
9866
 
        if (ctxt != NULL) {
9867
 
            /* TODO: User defined. */
9868
 
        }
9869
 
        /* XML Namespace. */
9870
 
        if (IS_STR_XML(attr->ns->prefix)) {
9871
 
            ns = xmlTreeEnsureXMLDecl(destDoc);
9872
 
        } else if (destParent == NULL) {
9873
 
            /*
9874
 
            * Store in @destDoc->oldNs.
9875
 
            */
9876
 
            ns = xmlDOMWrapStoreNs(destDoc, attr->ns->href, attr->ns->prefix);
9877
 
        } else {
9878
 
            /*
9879
 
            * Declare on @destParent.
9880
 
            */
9881
 
            if (xmlSearchNsByNamespaceStrict(destDoc, destParent, attr->ns->href,
9882
 
                &ns, 1) == -1)
9883
 
                goto internal_error;
9884
 
            if (ns == NULL) {
9885
 
                ns = xmlDOMWrapNSNormDeclareNsForced(destDoc, destParent,
9886
 
                    attr->ns->href, attr->ns->prefix, 1);
9887
 
            }
9888
 
        }
9889
 
        if (ns == NULL)
9890
 
            goto internal_error;
9891
 
        attr->ns = ns;
9892
 
    }
9893
 
 
9894
 
    XML_TREE_ADOPT_STR(attr->name);
9895
 
    attr->atype = 0;
9896
 
    attr->psvi = NULL;
9897
 
    /*
9898
 
    * Walk content.
9899
 
    */
9900
 
    if (attr->children == NULL)
9901
 
        return (0);
9902
 
    cur = attr->children;
9903
 
    if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))
9904
 
        goto internal_error;
9905
 
    while (cur != NULL) {
9906
 
        cur->doc = destDoc;
9907
 
        switch (cur->type) {
9908
 
            case XML_TEXT_NODE:
9909
 
            case XML_CDATA_SECTION_NODE:
9910
 
                XML_TREE_ADOPT_STR_2(cur->content)
9911
 
                break;
9912
 
            case XML_ENTITY_REF_NODE:
9913
 
                /*
9914
 
                * Remove reference to the entitity-node.
9915
 
                */
9916
 
                cur->content = NULL;
9917
 
                cur->children = NULL;
9918
 
                cur->last = NULL;
9919
 
                if ((destDoc->intSubset) || (destDoc->extSubset)) {
9920
 
                    xmlEntityPtr ent;
9921
 
                    /*
9922
 
                    * Assign new entity-node if available.
9923
 
                    */
9924
 
                    ent = xmlGetDocEntity(destDoc, cur->name);
9925
 
                    if (ent != NULL) {
9926
 
                        cur->content = ent->content;
9927
 
                        cur->children = (xmlNodePtr) ent;
9928
 
                        cur->last = (xmlNodePtr) ent;
9929
 
                    }
9930
 
                }
9931
 
                break;
9932
 
            default:
9933
 
                break;
9934
 
        }
9935
 
        if (cur->children != NULL) {
9936
 
            cur = cur->children;
9937
 
            continue;
9938
 
        }
9939
 
next_sibling:
9940
 
        if (cur == (xmlNodePtr) attr)
9941
 
            break;
9942
 
        if (cur->next != NULL)
9943
 
            cur = cur->next;
9944
 
        else {
9945
 
            cur = cur->parent;
9946
 
            goto next_sibling;
9947
 
        }
9948
 
    }
9949
 
    return (0);
9950
 
internal_error:
9951
 
    return (-1);
9952
 
}
9953
 
 
9954
 
/*
9955
 
* xmlDOMWrapAdoptNode:
9956
 
* @ctxt: the optional context for custom processing
9957
 
* @sourceDoc: the optional sourceDoc
9958
 
* @node: the node to start with
9959
 
* @destDoc: the destination doc
9960
 
* @destParent: the optional new parent of @node in @destDoc
9961
 
* @options: option flags
9962
 
*
9963
 
* References of out-of scope ns-decls are remapped to point to @destDoc:
9964
 
* 1) If @destParent is given, then nsDef entries on element-nodes are used
9965
 
* 2) If *no* @destParent is given, then @destDoc->oldNs entries are used
9966
 
*    This is the case when you have an unliked node and just want to move it
9967
 
*    to the context of
9968
 
*
9969
 
* If @destParent is given, it ensures that the tree is namespace
9970
 
* wellformed by creating additional ns-decls where needed.
9971
 
* Note that, since prefixes of already existent ns-decls can be
9972
 
* shadowed by this process, it could break QNames in attribute
9973
 
* values or element content.
9974
 
* NOTE: This function was not intensively tested.
9975
 
*
9976
 
* Returns 0 if the operation succeeded,
9977
 
*         1 if a node of unsupported type was given,
9978
 
*         2 if a node of not yet supported type was given and
9979
 
*         -1 on API/internal errors.
9980
 
*/
9981
 
int
9982
 
xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt,
9983
 
                    xmlDocPtr sourceDoc,
9984
 
                    xmlNodePtr node,
9985
 
                    xmlDocPtr destDoc,
9986
 
                    xmlNodePtr destParent,
9987
 
                    int options)
9988
 
{
9989
 
    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||
9990
 
        (destDoc == NULL) ||
9991
 
        ((destParent != NULL) && (destParent->doc != destDoc)))
9992
 
        return(-1);
9993
 
    /*
9994
 
    * Check node->doc sanity.
9995
 
    */
9996
 
    if ((node->doc != NULL) && (sourceDoc != NULL) &&
9997
 
        (node->doc != sourceDoc)) {
9998
 
        /*
9999
 
        * Might be an XIncluded node.
10000
 
        */
10001
 
        return (-1);
10002
 
    }
10003
 
    if (sourceDoc == NULL)
10004
 
        sourceDoc = node->doc;
10005
 
    if (sourceDoc == destDoc)
10006
 
        return (-1);
10007
 
    switch (node->type) {
10008
 
        case XML_ELEMENT_NODE:
10009
 
        case XML_ATTRIBUTE_NODE:
10010
 
        case XML_TEXT_NODE:
10011
 
        case XML_CDATA_SECTION_NODE:
10012
 
        case XML_ENTITY_REF_NODE:
10013
 
        case XML_PI_NODE:
10014
 
        case XML_COMMENT_NODE:
10015
 
            break;
10016
 
        case XML_DOCUMENT_FRAG_NODE:
10017
 
            /* TODO: Support document-fragment-nodes. */
10018
 
            return (2);
10019
 
        default:
10020
 
            return (1);
10021
 
    }
10022
 
    /*
10023
 
    * Unlink only if @node was not already added to @destParent.
10024
 
    */
10025
 
    if ((node->parent != NULL) && (destParent != node->parent))
10026
 
        xmlUnlinkNode(node);
10027
 
 
10028
 
    if (node->type == XML_ELEMENT_NODE) {
10029
 
            return (xmlDOMWrapAdoptBranch(ctxt, sourceDoc, node,
10030
 
                    destDoc, destParent, options));
10031
 
    } else if (node->type == XML_ATTRIBUTE_NODE) {
10032
 
            return (xmlDOMWrapAdoptAttr(ctxt, sourceDoc,
10033
 
                (xmlAttrPtr) node, destDoc, destParent, options));
10034
 
    } else {
10035
 
        xmlNodePtr cur = node;
10036
 
        int adoptStr = 1;
10037
 
 
10038
 
        cur->doc = destDoc;
10039
 
        /*
10040
 
        * Optimize string adoption.
10041
 
        */
10042
 
        if ((sourceDoc != NULL) &&
10043
 
            (sourceDoc->dict == destDoc->dict))
10044
 
                adoptStr = 0;
10045
 
        switch (node->type) {
10046
 
            case XML_TEXT_NODE:
10047
 
            case XML_CDATA_SECTION_NODE:
10048
 
                XML_TREE_ADOPT_STR_2(node->content)
10049
 
                    break;
10050
 
            case XML_ENTITY_REF_NODE:
10051
 
                /*
10052
 
                * Remove reference to the entitity-node.
10053
 
                */
10054
 
                node->content = NULL;
10055
 
                node->children = NULL;
10056
 
                node->last = NULL;
10057
 
                if ((destDoc->intSubset) || (destDoc->extSubset)) {
10058
 
                    xmlEntityPtr ent;
10059
 
                    /*
10060
 
                    * Assign new entity-node if available.
10061
 
                    */
10062
 
                    ent = xmlGetDocEntity(destDoc, node->name);
10063
 
                    if (ent != NULL) {
10064
 
                        node->content = ent->content;
10065
 
                        node->children = (xmlNodePtr) ent;
10066
 
                        node->last = (xmlNodePtr) ent;
10067
 
                    }
10068
 
                }
10069
 
                XML_TREE_ADOPT_STR(node->name)
10070
 
                break;
10071
 
            case XML_PI_NODE: {
10072
 
                XML_TREE_ADOPT_STR(node->name)
10073
 
                XML_TREE_ADOPT_STR_2(node->content)
10074
 
                break;
10075
 
            }
10076
 
            default:
10077
 
                break;
10078
 
        }
10079
 
    }
10080
 
    return (0);
10081
 
}
10082
 
 
10083
 
#define bottom_tree
10084
 
#include "elfgcchack.h"