Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * tree.c : implementation of access function for an XML tree.  | 
3  |  |  *  | 
4  |  |  * References:  | 
5  |  |  *   XHTML 1.0 W3C REC: http://www.w3.org/TR/2002/REC-xhtml1-20020801/  | 
6  |  |  *  | 
7  |  |  * See Copyright for the status of this software.  | 
8  |  |  *  | 
9  |  |  * daniel@veillard.com  | 
10  |  |  *  | 
11  |  |  */  | 
12  |  |  | 
13  |  | /* To avoid EBCDIC trouble when parsing on zOS */  | 
14  |  | #if defined(__MVS__)  | 
15  |  | #pragma convert("ISO8859-1") | 
16  |  | #endif  | 
17  |  |  | 
18  |  | #define IN_LIBXML  | 
19  |  | #include "libxml.h"  | 
20  |  |  | 
21  |  | #include <string.h> /* for memset() only ! */  | 
22  |  | #include <stddef.h>  | 
23  |  | #include <limits.h>  | 
24  |  | #include <ctype.h>  | 
25  |  | #include <stdlib.h>  | 
26  |  |  | 
27  |  | #ifdef LIBXML_ZLIB_ENABLED  | 
28  |  | #include <zlib.h>  | 
29  |  | #endif  | 
30  |  |  | 
31  |  | #include <libxml/xmlmemory.h>  | 
32  |  | #include <libxml/tree.h>  | 
33  |  | #include <libxml/parser.h>  | 
34  |  | #include <libxml/uri.h>  | 
35  |  | #include <libxml/entities.h>  | 
36  |  | #include <libxml/valid.h>  | 
37  |  | #include <libxml/xmlerror.h>  | 
38  |  | #include <libxml/parserInternals.h>  | 
39  |  | #include <libxml/globals.h>  | 
40  |  | #ifdef LIBXML_HTML_ENABLED  | 
41  |  | #include <libxml/HTMLtree.h>  | 
42  |  | #endif  | 
43  |  | #ifdef LIBXML_DEBUG_ENABLED  | 
44  |  | #include <libxml/debugXML.h>  | 
45  |  | #endif  | 
46  |  |  | 
47  |  | #include "private/buf.h"  | 
48  |  | #include "private/entities.h"  | 
49  |  | #include "private/error.h"  | 
50  |  | #include "private/tree.h"  | 
51  |  |  | 
52  |  | int __xmlRegisterCallbacks = 0;  | 
53  |  |  | 
54  |  | /************************************************************************  | 
55  |  |  *                  *  | 
56  |  |  *    Forward declarations          *  | 
57  |  |  *                  *  | 
58  |  |  ************************************************************************/  | 
59  |  |  | 
60  |  | static xmlNsPtr  | 
61  |  | xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns);  | 
62  |  |  | 
63  |  | static xmlChar* xmlGetPropNodeValueInternal(const xmlAttr *prop);  | 
64  |  |  | 
65  |  | /************************************************************************  | 
66  |  |  *                  *  | 
67  |  |  *    Tree memory error handler       *  | 
68  |  |  *                  *  | 
69  |  |  ************************************************************************/  | 
70  |  | /**  | 
71  |  |  * xmlTreeErrMemory:  | 
72  |  |  * @extra:  extra information  | 
73  |  |  *  | 
74  |  |  * Handle an out of memory condition  | 
75  |  |  */  | 
76  |  | static void  | 
77  |  | xmlTreeErrMemory(const char *extra)  | 
78  | 0  | { | 
79  | 0  |     __xmlSimpleError(XML_FROM_TREE, XML_ERR_NO_MEMORY, NULL, NULL, extra);  | 
80  | 0  | }  | 
81  |  |  | 
82  |  | /**  | 
83  |  |  * xmlTreeErr:  | 
84  |  |  * @code:  the error number  | 
85  |  |  * @extra:  extra information  | 
86  |  |  *  | 
87  |  |  * Handle an out of memory condition  | 
88  |  |  */  | 
89  |  | static void  | 
90  |  | xmlTreeErr(int code, xmlNodePtr node, const char *extra)  | 
91  | 0  | { | 
92  | 0  |     const char *msg = NULL;  | 
93  |  | 
  | 
94  | 0  |     switch(code) { | 
95  | 0  |         case XML_TREE_INVALID_HEX:  | 
96  | 0  |       msg = "invalid hexadecimal character value\n";  | 
97  | 0  |       break;  | 
98  | 0  |   case XML_TREE_INVALID_DEC:  | 
99  | 0  |       msg = "invalid decimal character value\n";  | 
100  | 0  |       break;  | 
101  | 0  |   case XML_TREE_UNTERMINATED_ENTITY:  | 
102  | 0  |       msg = "unterminated entity reference %15s\n";  | 
103  | 0  |       break;  | 
104  | 0  |   case XML_TREE_NOT_UTF8:  | 
105  | 0  |       msg = "string is not in UTF-8\n";  | 
106  | 0  |       break;  | 
107  | 0  |   default:  | 
108  | 0  |       msg = "unexpected error number\n";  | 
109  | 0  |     }  | 
110  | 0  |     __xmlSimpleError(XML_FROM_TREE, code, node, msg, extra);  | 
111  | 0  | }  | 
112  |  |  | 
113  |  | /************************************************************************  | 
114  |  |  *                  *  | 
115  |  |  *    A few static variables and macros     *  | 
116  |  |  *                  *  | 
117  |  |  ************************************************************************/  | 
118  |  | /* #undef xmlStringText */  | 
119  |  | const xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 }; | 
120  |  | /* #undef xmlStringTextNoenc */  | 
121  |  | const xmlChar xmlStringTextNoenc[] =  | 
122  |  |               { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 }; | 
123  |  | /* #undef xmlStringComment */  | 
124  |  | const xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 }; | 
125  |  |  | 
126  |  | static int xmlCompressMode = 0;  | 
127  |  | static int xmlCheckDTD = 1;  | 
128  |  |  | 
129  | 3.70M  | #define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) {   \ | 
130  | 3.70M  |     xmlNodePtr ulccur = (n)->children;          \  | 
131  | 3.70M  |     if (ulccur == NULL) {           \ | 
132  | 0  |         (n)->last = NULL;           \  | 
133  | 3.70M  |     } else {               \ | 
134  | 3.70M  |         while (ulccur->next != NULL) {         \ | 
135  | 0  |     ulccur->parent = (n);         \  | 
136  | 0  |     ulccur = ulccur->next;          \  | 
137  | 0  |   }                \  | 
138  | 3.70M  |   ulccur->parent = (n);           \  | 
139  | 3.70M  |   (n)->last = ulccur;           \  | 
140  | 3.70M  | }}  | 
141  |  |  | 
142  | 0  | #define IS_STR_XML(str) ((str != NULL) && (str[0] == 'x') && \  | 
143  | 0  |   (str[1] == 'm') && (str[2] == 'l') && (str[3] == 0))  | 
144  |  |  | 
145  |  | /* #define DEBUG_BUFFER */  | 
146  |  | /* #define DEBUG_TREE */  | 
147  |  |  | 
148  |  | /************************************************************************  | 
149  |  |  *                  *  | 
150  |  |  *    Functions to move to entities.c once the    *  | 
151  |  |  *    API freeze is smoothen and they can be made public. *  | 
152  |  |  *                  *  | 
153  |  |  ************************************************************************/  | 
154  |  | #include <libxml/hash.h>  | 
155  |  |  | 
156  |  | #ifdef LIBXML_TREE_ENABLED  | 
157  |  | /**  | 
158  |  |  * xmlGetEntityFromDtd:  | 
159  |  |  * @dtd:  A pointer to the DTD to search  | 
160  |  |  * @name:  The entity name  | 
161  |  |  *  | 
162  |  |  * Do an entity lookup in the DTD entity hash table and  | 
163  |  |  * return the corresponding entity, if found.  | 
164  |  |  *  | 
165  |  |  * Returns A pointer to the entity structure or NULL if not found.  | 
166  |  |  */  | 
167  |  | static xmlEntityPtr  | 
168  | 0  | xmlGetEntityFromDtd(const xmlDtd *dtd, const xmlChar *name) { | 
169  | 0  |     xmlEntitiesTablePtr table;  | 
170  |  | 
  | 
171  | 0  |     if((dtd != NULL) && (dtd->entities != NULL)) { | 
172  | 0  |   table = (xmlEntitiesTablePtr) dtd->entities;  | 
173  | 0  |   return((xmlEntityPtr) xmlHashLookup(table, name));  | 
174  |  |   /* return(xmlGetEntityFromTable(table, name)); */  | 
175  | 0  |     }  | 
176  | 0  |     return(NULL);  | 
177  | 0  | }  | 
178  |  | /**  | 
179  |  |  * xmlGetParameterEntityFromDtd:  | 
180  |  |  * @dtd:  A pointer to the DTD to search  | 
181  |  |  * @name:  The entity name  | 
182  |  |  *  | 
183  |  |  * Do an entity lookup in the DTD parameter entity hash table and  | 
184  |  |  * return the corresponding entity, if found.  | 
185  |  |  *  | 
186  |  |  * Returns A pointer to the entity structure or NULL if not found.  | 
187  |  |  */  | 
188  |  | static xmlEntityPtr  | 
189  | 0  | xmlGetParameterEntityFromDtd(const xmlDtd *dtd, const xmlChar *name) { | 
190  | 0  |     xmlEntitiesTablePtr table;  | 
191  |  | 
  | 
192  | 0  |     if ((dtd != NULL) && (dtd->pentities != NULL)) { | 
193  | 0  |   table = (xmlEntitiesTablePtr) dtd->pentities;  | 
194  | 0  |   return((xmlEntityPtr) xmlHashLookup(table, name));  | 
195  |  |   /* return(xmlGetEntityFromTable(table, name)); */  | 
196  | 0  |     }  | 
197  | 0  |     return(NULL);  | 
198  | 0  | }  | 
199  |  | #endif /* LIBXML_TREE_ENABLED */  | 
200  |  |  | 
201  |  | /************************************************************************  | 
202  |  |  *                  *  | 
203  |  |  *      QName handling helper       *  | 
204  |  |  *                  *  | 
205  |  |  ************************************************************************/  | 
206  |  |  | 
207  |  | /**  | 
208  |  |  * xmlBuildQName:  | 
209  |  |  * @ncname:  the Name  | 
210  |  |  * @prefix:  the prefix  | 
211  |  |  * @memory:  preallocated memory  | 
212  |  |  * @len:  preallocated memory length  | 
213  |  |  *  | 
214  |  |  * Builds the QName @prefix:@ncname in @memory if there is enough space  | 
215  |  |  * and prefix is not NULL nor empty, otherwise allocate a new string.  | 
216  |  |  * If prefix is NULL or empty it returns ncname.  | 
217  |  |  *  | 
218  |  |  * Returns the new string which must be freed by the caller if different from  | 
219  |  |  *         @memory and @ncname or NULL in case of error  | 
220  |  |  */  | 
221  |  | xmlChar *  | 
222  |  | xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix,  | 
223  | 50.6k  |         xmlChar *memory, int len) { | 
224  | 50.6k  |     int lenn, lenp;  | 
225  | 50.6k  |     xmlChar *ret;  | 
226  |  |  | 
227  | 50.6k  |     if (ncname == NULL) return(NULL);  | 
228  | 50.6k  |     if (prefix == NULL) return((xmlChar *) ncname);  | 
229  |  |  | 
230  | 50.6k  |     lenn = strlen((char *) ncname);  | 
231  | 50.6k  |     lenp = strlen((char *) prefix);  | 
232  |  |  | 
233  | 50.6k  |     if ((memory == NULL) || (len < lenn + lenp + 2)) { | 
234  | 50.6k  |   ret = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);  | 
235  | 50.6k  |   if (ret == NULL) { | 
236  | 0  |       xmlTreeErrMemory("building QName"); | 
237  | 0  |       return(NULL);  | 
238  | 0  |   }  | 
239  | 50.6k  |     } else { | 
240  | 0  |   ret = memory;  | 
241  | 0  |     }  | 
242  | 50.6k  |     memcpy(&ret[0], prefix, lenp);  | 
243  | 50.6k  |     ret[lenp] = ':';  | 
244  | 50.6k  |     memcpy(&ret[lenp + 1], ncname, lenn);  | 
245  | 50.6k  |     ret[lenn + lenp + 1] = 0;  | 
246  | 50.6k  |     return(ret);  | 
247  | 50.6k  | }  | 
248  |  |  | 
249  |  | /**  | 
250  |  |  * xmlSplitQName2:  | 
251  |  |  * @name:  the full QName  | 
252  |  |  * @prefix:  a xmlChar **  | 
253  |  |  *  | 
254  |  |  * parse an XML qualified name string  | 
255  |  |  *  | 
256  |  |  * [NS 5] QName ::= (Prefix ':')? LocalPart  | 
257  |  |  *  | 
258  |  |  * [NS 6] Prefix ::= NCName  | 
259  |  |  *  | 
260  |  |  * [NS 7] LocalPart ::= NCName  | 
261  |  |  *  | 
262  |  |  * Returns NULL if the name doesn't have a prefix. Otherwise, returns the  | 
263  |  |  * local part, and prefix is updated to get the Prefix. Both the return value  | 
264  |  |  * and the prefix must be freed by the caller.  | 
265  |  |  */  | 
266  |  | xmlChar *  | 
267  | 33.7k  | xmlSplitQName2(const xmlChar *name, xmlChar **prefix) { | 
268  | 33.7k  |     int len = 0;  | 
269  | 33.7k  |     xmlChar *ret = NULL;  | 
270  |  |  | 
271  | 33.7k  |     if (prefix == NULL) return(NULL);  | 
272  | 33.7k  |     *prefix = NULL;  | 
273  | 33.7k  |     if (name == NULL) return(NULL);  | 
274  |  |  | 
275  |  | #ifndef XML_XML_NAMESPACE  | 
276  |  |     /* xml: prefix is not really a namespace */  | 
277  |  |     if ((name[0] == 'x') && (name[1] == 'm') &&  | 
278  |  |         (name[2] == 'l') && (name[3] == ':'))  | 
279  |  |   return(NULL);  | 
280  |  | #endif  | 
281  |  |  | 
282  |  |     /* nasty but valid */  | 
283  | 33.7k  |     if (name[0] == ':')  | 
284  | 157  |   return(NULL);  | 
285  |  |  | 
286  |  |     /*  | 
287  |  |      * we are not trying to validate but just to cut, and yes it will  | 
288  |  |      * work even if this is as set of UTF-8 encoded chars  | 
289  |  |      */  | 
290  | 168k  |     while ((name[len] != 0) && (name[len] != ':'))  | 
291  | 135k  |   len++;  | 
292  |  |  | 
293  | 33.6k  |     if (name[len] == 0)  | 
294  | 31.7k  |   return(NULL);  | 
295  |  |  | 
296  | 1.81k  |     *prefix = xmlStrndup(name, len);  | 
297  | 1.81k  |     if (*prefix == NULL) { | 
298  | 0  |   xmlTreeErrMemory("QName split"); | 
299  | 0  |   return(NULL);  | 
300  | 0  |     }  | 
301  | 1.81k  |     ret = xmlStrdup(&name[len + 1]);  | 
302  | 1.81k  |     if (ret == NULL) { | 
303  | 0  |   xmlTreeErrMemory("QName split"); | 
304  | 0  |   if (*prefix != NULL) { | 
305  | 0  |       xmlFree(*prefix);  | 
306  | 0  |       *prefix = NULL;  | 
307  | 0  |   }  | 
308  | 0  |   return(NULL);  | 
309  | 0  |     }  | 
310  |  |  | 
311  | 1.81k  |     return(ret);  | 
312  | 1.81k  | }  | 
313  |  |  | 
314  |  | /**  | 
315  |  |  * xmlSplitQName3:  | 
316  |  |  * @name:  the full QName  | 
317  |  |  * @len: an int *  | 
318  |  |  *  | 
319  |  |  * parse an XML qualified name string,i  | 
320  |  |  *  | 
321  |  |  * returns NULL if it is not a Qualified Name, otherwise, update len  | 
322  |  |  *         with the length in byte of the prefix and return a pointer  | 
323  |  |  *         to the start of the name without the prefix  | 
324  |  |  */  | 
325  |  |  | 
326  |  | const xmlChar *  | 
327  | 0  | xmlSplitQName3(const xmlChar *name, int *len) { | 
328  | 0  |     int l = 0;  | 
329  |  | 
  | 
330  | 0  |     if (name == NULL) return(NULL);  | 
331  | 0  |     if (len == NULL) return(NULL);  | 
332  |  |  | 
333  |  |     /* nasty but valid */  | 
334  | 0  |     if (name[0] == ':')  | 
335  | 0  |   return(NULL);  | 
336  |  |  | 
337  |  |     /*  | 
338  |  |      * we are not trying to validate but just to cut, and yes it will  | 
339  |  |      * work even if this is as set of UTF-8 encoded chars  | 
340  |  |      */  | 
341  | 0  |     while ((name[l] != 0) && (name[l] != ':'))  | 
342  | 0  |   l++;  | 
343  |  | 
  | 
344  | 0  |     if (name[l] == 0)  | 
345  | 0  |   return(NULL);  | 
346  |  |  | 
347  | 0  |     *len = l;  | 
348  |  | 
  | 
349  | 0  |     return(&name[l+1]);  | 
350  | 0  | }  | 
351  |  |  | 
352  |  | /************************************************************************  | 
353  |  |  *                  *  | 
354  |  |  *    Check Name, NCName and QName strings      *  | 
355  |  |  *                  *  | 
356  |  |  ************************************************************************/  | 
357  |  |  | 
358  | 0  | #define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)  | 
359  |  |  | 
360  |  | #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_LEGACY_ENABLED)  | 
361  |  | /**  | 
362  |  |  * xmlValidateNCName:  | 
363  |  |  * @value: the value to check  | 
364  |  |  * @space: allow spaces in front and end of the string  | 
365  |  |  *  | 
366  |  |  * Check that a value conforms to the lexical space of NCName  | 
367  |  |  *  | 
368  |  |  * Returns 0 if this validates, a positive error code number otherwise  | 
369  |  |  *         and -1 in case of internal or API error.  | 
370  |  |  */  | 
371  |  | int  | 
372  | 0  | xmlValidateNCName(const xmlChar *value, int space) { | 
373  | 0  |     const xmlChar *cur = value;  | 
374  | 0  |     int c,l;  | 
375  |  | 
  | 
376  | 0  |     if (value == NULL)  | 
377  | 0  |         return(-1);  | 
378  |  |  | 
379  |  |     /*  | 
380  |  |      * First quick algorithm for ASCII range  | 
381  |  |      */  | 
382  | 0  |     if (space)  | 
383  | 0  |   while (IS_BLANK_CH(*cur)) cur++;  | 
384  | 0  |     if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||  | 
385  | 0  |   (*cur == '_'))  | 
386  | 0  |   cur++;  | 
387  | 0  |     else  | 
388  | 0  |   goto try_complex;  | 
389  | 0  |     while (((*cur >= 'a') && (*cur <= 'z')) ||  | 
390  | 0  |      ((*cur >= 'A') && (*cur <= 'Z')) ||  | 
391  | 0  |      ((*cur >= '0') && (*cur <= '9')) ||  | 
392  | 0  |      (*cur == '_') || (*cur == '-') || (*cur == '.'))  | 
393  | 0  |   cur++;  | 
394  | 0  |     if (space)  | 
395  | 0  |   while (IS_BLANK_CH(*cur)) cur++;  | 
396  | 0  |     if (*cur == 0)  | 
397  | 0  |   return(0);  | 
398  |  |  | 
399  | 0  | try_complex:  | 
400  |  |     /*  | 
401  |  |      * Second check for chars outside the ASCII range  | 
402  |  |      */  | 
403  | 0  |     cur = value;  | 
404  | 0  |     c = CUR_SCHAR(cur, l);  | 
405  | 0  |     if (space) { | 
406  | 0  |   while (IS_BLANK(c)) { | 
407  | 0  |       cur += l;  | 
408  | 0  |       c = CUR_SCHAR(cur, l);  | 
409  | 0  |   }  | 
410  | 0  |     }  | 
411  | 0  |     if ((!IS_LETTER(c)) && (c != '_'))  | 
412  | 0  |   return(1);  | 
413  | 0  |     cur += l;  | 
414  | 0  |     c = CUR_SCHAR(cur, l);  | 
415  | 0  |     while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||  | 
416  | 0  |      (c == '-') || (c == '_') || IS_COMBINING(c) ||  | 
417  | 0  |      IS_EXTENDER(c)) { | 
418  | 0  |   cur += l;  | 
419  | 0  |   c = CUR_SCHAR(cur, l);  | 
420  | 0  |     }  | 
421  | 0  |     if (space) { | 
422  | 0  |   while (IS_BLANK(c)) { | 
423  | 0  |       cur += l;  | 
424  | 0  |       c = CUR_SCHAR(cur, l);  | 
425  | 0  |   }  | 
426  | 0  |     }  | 
427  | 0  |     if (c != 0)  | 
428  | 0  |   return(1);  | 
429  |  |  | 
430  | 0  |     return(0);  | 
431  | 0  | }  | 
432  |  | #endif  | 
433  |  |  | 
434  |  | #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)  | 
435  |  | /**  | 
436  |  |  * xmlValidateQName:  | 
437  |  |  * @value: the value to check  | 
438  |  |  * @space: allow spaces in front and end of the string  | 
439  |  |  *  | 
440  |  |  * Check that a value conforms to the lexical space of QName  | 
441  |  |  *  | 
442  |  |  * Returns 0 if this validates, a positive error code number otherwise  | 
443  |  |  *         and -1 in case of internal or API error.  | 
444  |  |  */  | 
445  |  | int  | 
446  | 0  | xmlValidateQName(const xmlChar *value, int space) { | 
447  | 0  |     const xmlChar *cur = value;  | 
448  | 0  |     int c,l;  | 
449  |  | 
  | 
450  | 0  |     if (value == NULL)  | 
451  | 0  |         return(-1);  | 
452  |  |     /*  | 
453  |  |      * First quick algorithm for ASCII range  | 
454  |  |      */  | 
455  | 0  |     if (space)  | 
456  | 0  |   while (IS_BLANK_CH(*cur)) cur++;  | 
457  | 0  |     if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||  | 
458  | 0  |   (*cur == '_'))  | 
459  | 0  |   cur++;  | 
460  | 0  |     else  | 
461  | 0  |   goto try_complex;  | 
462  | 0  |     while (((*cur >= 'a') && (*cur <= 'z')) ||  | 
463  | 0  |      ((*cur >= 'A') && (*cur <= 'Z')) ||  | 
464  | 0  |      ((*cur >= '0') && (*cur <= '9')) ||  | 
465  | 0  |      (*cur == '_') || (*cur == '-') || (*cur == '.'))  | 
466  | 0  |   cur++;  | 
467  | 0  |     if (*cur == ':') { | 
468  | 0  |   cur++;  | 
469  | 0  |   if (((*cur >= 'a') && (*cur <= 'z')) ||  | 
470  | 0  |       ((*cur >= 'A') && (*cur <= 'Z')) ||  | 
471  | 0  |       (*cur == '_'))  | 
472  | 0  |       cur++;  | 
473  | 0  |   else  | 
474  | 0  |       goto try_complex;  | 
475  | 0  |   while (((*cur >= 'a') && (*cur <= 'z')) ||  | 
476  | 0  |          ((*cur >= 'A') && (*cur <= 'Z')) ||  | 
477  | 0  |          ((*cur >= '0') && (*cur <= '9')) ||  | 
478  | 0  |          (*cur == '_') || (*cur == '-') || (*cur == '.'))  | 
479  | 0  |       cur++;  | 
480  | 0  |     }  | 
481  | 0  |     if (space)  | 
482  | 0  |   while (IS_BLANK_CH(*cur)) cur++;  | 
483  | 0  |     if (*cur == 0)  | 
484  | 0  |   return(0);  | 
485  |  |  | 
486  | 0  | try_complex:  | 
487  |  |     /*  | 
488  |  |      * Second check for chars outside the ASCII range  | 
489  |  |      */  | 
490  | 0  |     cur = value;  | 
491  | 0  |     c = CUR_SCHAR(cur, l);  | 
492  | 0  |     if (space) { | 
493  | 0  |   while (IS_BLANK(c)) { | 
494  | 0  |       cur += l;  | 
495  | 0  |       c = CUR_SCHAR(cur, l);  | 
496  | 0  |   }  | 
497  | 0  |     }  | 
498  | 0  |     if ((!IS_LETTER(c)) && (c != '_'))  | 
499  | 0  |   return(1);  | 
500  | 0  |     cur += l;  | 
501  | 0  |     c = CUR_SCHAR(cur, l);  | 
502  | 0  |     while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||  | 
503  | 0  |      (c == '-') || (c == '_') || IS_COMBINING(c) ||  | 
504  | 0  |      IS_EXTENDER(c)) { | 
505  | 0  |   cur += l;  | 
506  | 0  |   c = CUR_SCHAR(cur, l);  | 
507  | 0  |     }  | 
508  | 0  |     if (c == ':') { | 
509  | 0  |   cur += l;  | 
510  | 0  |   c = CUR_SCHAR(cur, l);  | 
511  | 0  |   if ((!IS_LETTER(c)) && (c != '_'))  | 
512  | 0  |       return(1);  | 
513  | 0  |   cur += l;  | 
514  | 0  |   c = CUR_SCHAR(cur, l);  | 
515  | 0  |   while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') ||  | 
516  | 0  |          (c == '-') || (c == '_') || IS_COMBINING(c) ||  | 
517  | 0  |          IS_EXTENDER(c)) { | 
518  | 0  |       cur += l;  | 
519  | 0  |       c = CUR_SCHAR(cur, l);  | 
520  | 0  |   }  | 
521  | 0  |     }  | 
522  | 0  |     if (space) { | 
523  | 0  |   while (IS_BLANK(c)) { | 
524  | 0  |       cur += l;  | 
525  | 0  |       c = CUR_SCHAR(cur, l);  | 
526  | 0  |   }  | 
527  | 0  |     }  | 
528  | 0  |     if (c != 0)  | 
529  | 0  |   return(1);  | 
530  | 0  |     return(0);  | 
531  | 0  | }  | 
532  |  |  | 
533  |  | /**  | 
534  |  |  * xmlValidateName:  | 
535  |  |  * @value: the value to check  | 
536  |  |  * @space: allow spaces in front and end of the string  | 
537  |  |  *  | 
538  |  |  * Check that a value conforms to the lexical space of Name  | 
539  |  |  *  | 
540  |  |  * Returns 0 if this validates, a positive error code number otherwise  | 
541  |  |  *         and -1 in case of internal or API error.  | 
542  |  |  */  | 
543  |  | int  | 
544  | 0  | xmlValidateName(const xmlChar *value, int space) { | 
545  | 0  |     const xmlChar *cur = value;  | 
546  | 0  |     int c,l;  | 
547  |  | 
  | 
548  | 0  |     if (value == NULL)  | 
549  | 0  |         return(-1);  | 
550  |  |     /*  | 
551  |  |      * First quick algorithm for ASCII range  | 
552  |  |      */  | 
553  | 0  |     if (space)  | 
554  | 0  |   while (IS_BLANK_CH(*cur)) cur++;  | 
555  | 0  |     if (((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= 'A') && (*cur <= 'Z')) ||  | 
556  | 0  |   (*cur == '_') || (*cur == ':'))  | 
557  | 0  |   cur++;  | 
558  | 0  |     else  | 
559  | 0  |   goto try_complex;  | 
560  | 0  |     while (((*cur >= 'a') && (*cur <= 'z')) ||  | 
561  | 0  |      ((*cur >= 'A') && (*cur <= 'Z')) ||  | 
562  | 0  |      ((*cur >= '0') && (*cur <= '9')) ||  | 
563  | 0  |      (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))  | 
564  | 0  |   cur++;  | 
565  | 0  |     if (space)  | 
566  | 0  |   while (IS_BLANK_CH(*cur)) cur++;  | 
567  | 0  |     if (*cur == 0)  | 
568  | 0  |   return(0);  | 
569  |  |  | 
570  | 0  | try_complex:  | 
571  |  |     /*  | 
572  |  |      * Second check for chars outside the ASCII range  | 
573  |  |      */  | 
574  | 0  |     cur = value;  | 
575  | 0  |     c = CUR_SCHAR(cur, l);  | 
576  | 0  |     if (space) { | 
577  | 0  |   while (IS_BLANK(c)) { | 
578  | 0  |       cur += l;  | 
579  | 0  |       c = CUR_SCHAR(cur, l);  | 
580  | 0  |   }  | 
581  | 0  |     }  | 
582  | 0  |     if ((!IS_LETTER(c)) && (c != '_') && (c != ':'))  | 
583  | 0  |   return(1);  | 
584  | 0  |     cur += l;  | 
585  | 0  |     c = CUR_SCHAR(cur, l);  | 
586  | 0  |     while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||  | 
587  | 0  |      (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) { | 
588  | 0  |   cur += l;  | 
589  | 0  |   c = CUR_SCHAR(cur, l);  | 
590  | 0  |     }  | 
591  | 0  |     if (space) { | 
592  | 0  |   while (IS_BLANK(c)) { | 
593  | 0  |       cur += l;  | 
594  | 0  |       c = CUR_SCHAR(cur, l);  | 
595  | 0  |   }  | 
596  | 0  |     }  | 
597  | 0  |     if (c != 0)  | 
598  | 0  |   return(1);  | 
599  | 0  |     return(0);  | 
600  | 0  | }  | 
601  |  |  | 
602  |  | /**  | 
603  |  |  * xmlValidateNMToken:  | 
604  |  |  * @value: the value to check  | 
605  |  |  * @space: allow spaces in front and end of the string  | 
606  |  |  *  | 
607  |  |  * Check that a value conforms to the lexical space of NMToken  | 
608  |  |  *  | 
609  |  |  * Returns 0 if this validates, a positive error code number otherwise  | 
610  |  |  *         and -1 in case of internal or API error.  | 
611  |  |  */  | 
612  |  | int  | 
613  | 0  | xmlValidateNMToken(const xmlChar *value, int space) { | 
614  | 0  |     const xmlChar *cur = value;  | 
615  | 0  |     int c,l;  | 
616  |  | 
  | 
617  | 0  |     if (value == NULL)  | 
618  | 0  |         return(-1);  | 
619  |  |     /*  | 
620  |  |      * First quick algorithm for ASCII range  | 
621  |  |      */  | 
622  | 0  |     if (space)  | 
623  | 0  |   while (IS_BLANK_CH(*cur)) cur++;  | 
624  | 0  |     if (((*cur >= 'a') && (*cur <= 'z')) ||  | 
625  | 0  |         ((*cur >= 'A') && (*cur <= 'Z')) ||  | 
626  | 0  |         ((*cur >= '0') && (*cur <= '9')) ||  | 
627  | 0  |         (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))  | 
628  | 0  |   cur++;  | 
629  | 0  |     else  | 
630  | 0  |   goto try_complex;  | 
631  | 0  |     while (((*cur >= 'a') && (*cur <= 'z')) ||  | 
632  | 0  |      ((*cur >= 'A') && (*cur <= 'Z')) ||  | 
633  | 0  |      ((*cur >= '0') && (*cur <= '9')) ||  | 
634  | 0  |      (*cur == '_') || (*cur == '-') || (*cur == '.') || (*cur == ':'))  | 
635  | 0  |   cur++;  | 
636  | 0  |     if (space)  | 
637  | 0  |   while (IS_BLANK_CH(*cur)) cur++;  | 
638  | 0  |     if (*cur == 0)  | 
639  | 0  |   return(0);  | 
640  |  |  | 
641  | 0  | try_complex:  | 
642  |  |     /*  | 
643  |  |      * Second check for chars outside the ASCII range  | 
644  |  |      */  | 
645  | 0  |     cur = value;  | 
646  | 0  |     c = CUR_SCHAR(cur, l);  | 
647  | 0  |     if (space) { | 
648  | 0  |   while (IS_BLANK(c)) { | 
649  | 0  |       cur += l;  | 
650  | 0  |       c = CUR_SCHAR(cur, l);  | 
651  | 0  |   }  | 
652  | 0  |     }  | 
653  | 0  |     if (!(IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||  | 
654  | 0  |         (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)))  | 
655  | 0  |   return(1);  | 
656  | 0  |     cur += l;  | 
657  | 0  |     c = CUR_SCHAR(cur, l);  | 
658  | 0  |     while (IS_LETTER(c) || IS_DIGIT(c) || (c == '.') || (c == ':') ||  | 
659  | 0  |      (c == '-') || (c == '_') || IS_COMBINING(c) || IS_EXTENDER(c)) { | 
660  | 0  |   cur += l;  | 
661  | 0  |   c = CUR_SCHAR(cur, l);  | 
662  | 0  |     }  | 
663  | 0  |     if (space) { | 
664  | 0  |   while (IS_BLANK(c)) { | 
665  | 0  |       cur += l;  | 
666  | 0  |       c = CUR_SCHAR(cur, l);  | 
667  | 0  |   }  | 
668  | 0  |     }  | 
669  | 0  |     if (c != 0)  | 
670  | 0  |   return(1);  | 
671  | 0  |     return(0);  | 
672  | 0  | }  | 
673  |  | #endif /* LIBXML_TREE_ENABLED */  | 
674  |  |  | 
675  |  | /************************************************************************  | 
676  |  |  *                  *  | 
677  |  |  *    Allocation and deallocation of basic structures   *  | 
678  |  |  *                  *  | 
679  |  |  ************************************************************************/  | 
680  |  |  | 
681  |  | /**  | 
682  |  |  * xmlSetBufferAllocationScheme:  | 
683  |  |  * @scheme:  allocation method to use  | 
684  |  |  *  | 
685  |  |  * Set the buffer allocation method.  Types are  | 
686  |  |  * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down  | 
687  |  |  * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,  | 
688  |  |  *                             improves performance  | 
689  |  |  */  | 
690  |  | void  | 
691  | 0  | xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) { | 
692  | 0  |     if ((scheme == XML_BUFFER_ALLOC_EXACT) ||  | 
693  | 0  |         (scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||  | 
694  | 0  |         (scheme == XML_BUFFER_ALLOC_HYBRID))  | 
695  | 0  |   xmlBufferAllocScheme = scheme;  | 
696  | 0  | }  | 
697  |  |  | 
698  |  | /**  | 
699  |  |  * xmlGetBufferAllocationScheme:  | 
700  |  |  *  | 
701  |  |  * Types are  | 
702  |  |  * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down  | 
703  |  |  * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed,  | 
704  |  |  *                             improves performance  | 
705  |  |  * XML_BUFFER_ALLOC_HYBRID - use exact sizes on small strings to keep memory usage tight  | 
706  |  |  *                            in normal usage, and doubleit on large strings to avoid  | 
707  |  |  *                            pathological performance.  | 
708  |  |  *  | 
709  |  |  * Returns the current allocation scheme  | 
710  |  |  */  | 
711  |  | xmlBufferAllocationScheme  | 
712  | 0  | xmlGetBufferAllocationScheme(void) { | 
713  | 0  |     return(xmlBufferAllocScheme);  | 
714  | 0  | }  | 
715  |  |  | 
716  |  | /**  | 
717  |  |  * xmlNewNs:  | 
718  |  |  * @node:  the element carrying the namespace  | 
719  |  |  * @href:  the URI associated  | 
720  |  |  * @prefix:  the prefix for the namespace  | 
721  |  |  *  | 
722  |  |  * Creation of a new Namespace. This function will refuse to create  | 
723  |  |  * a namespace with a similar prefix than an existing one present on this  | 
724  |  |  * node.  | 
725  |  |  * Note that for a default namespace, @prefix should be NULL.  | 
726  |  |  *  | 
727  |  |  * We use href==NULL in the case of an element creation where the namespace  | 
728  |  |  * was not defined.  | 
729  |  |  *  | 
730  |  |  * Returns a new namespace pointer or NULL  | 
731  |  |  */  | 
732  |  | xmlNsPtr  | 
733  | 424k  | xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) { | 
734  | 424k  |     xmlNsPtr cur;  | 
735  |  |  | 
736  | 424k  |     if ((node != NULL) && (node->type != XML_ELEMENT_NODE))  | 
737  | 0  |   return(NULL);  | 
738  |  |  | 
739  | 424k  |     if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) { | 
740  |  |         /* xml namespace is predefined, no need to add it */  | 
741  | 0  |         if (xmlStrEqual(href, XML_XML_NAMESPACE))  | 
742  | 0  |             return(NULL);  | 
743  |  |  | 
744  |  |         /*  | 
745  |  |          * Problem, this is an attempt to bind xml prefix to a wrong  | 
746  |  |          * namespace, which breaks  | 
747  |  |          * Namespace constraint: Reserved Prefixes and Namespace Names  | 
748  |  |          * from XML namespace. But documents authors may not care in  | 
749  |  |          * their context so let's proceed.  | 
750  |  |          */  | 
751  | 0  |     }  | 
752  |  |  | 
753  |  |     /*  | 
754  |  |      * Allocate a new Namespace and fill the fields.  | 
755  |  |      */  | 
756  | 424k  |     cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));  | 
757  | 424k  |     if (cur == NULL) { | 
758  | 0  |   xmlTreeErrMemory("building namespace"); | 
759  | 0  |   return(NULL);  | 
760  | 0  |     }  | 
761  | 424k  |     memset(cur, 0, sizeof(xmlNs));  | 
762  | 424k  |     cur->type = XML_LOCAL_NAMESPACE;  | 
763  |  |  | 
764  | 424k  |     if (href != NULL)  | 
765  | 424k  |   cur->href = xmlStrdup(href);  | 
766  | 424k  |     if (prefix != NULL)  | 
767  | 424k  |   cur->prefix = xmlStrdup(prefix);  | 
768  |  |  | 
769  |  |     /*  | 
770  |  |      * Add it at the end to preserve parsing order ...  | 
771  |  |      * and checks for existing use of the prefix  | 
772  |  |      */  | 
773  | 424k  |     if (node != NULL) { | 
774  | 413k  |   if (node->nsDef == NULL) { | 
775  | 413k  |       node->nsDef = cur;  | 
776  | 413k  |   } else { | 
777  | 0  |       xmlNsPtr prev = node->nsDef;  | 
778  |  | 
  | 
779  | 0  |       if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||  | 
780  | 0  |     (xmlStrEqual(prev->prefix, cur->prefix))) { | 
781  | 0  |     xmlFreeNs(cur);  | 
782  | 0  |     return(NULL);  | 
783  | 0  |       }  | 
784  | 0  |       while (prev->next != NULL) { | 
785  | 0  |           prev = prev->next;  | 
786  | 0  |     if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||  | 
787  | 0  |         (xmlStrEqual(prev->prefix, cur->prefix))) { | 
788  | 0  |         xmlFreeNs(cur);  | 
789  | 0  |         return(NULL);  | 
790  | 0  |     }  | 
791  | 0  |       }  | 
792  | 0  |       prev->next = cur;  | 
793  | 0  |   }  | 
794  | 413k  |     }  | 
795  | 424k  |     return(cur);  | 
796  | 424k  | }  | 
797  |  |  | 
798  |  | /**  | 
799  |  |  * xmlSetNs:  | 
800  |  |  * @node:  a node in the document  | 
801  |  |  * @ns:  a namespace pointer  | 
802  |  |  *  | 
803  |  |  * Associate a namespace to a node, a posteriori.  | 
804  |  |  */  | 
805  |  | void  | 
806  | 0  | xmlSetNs(xmlNodePtr node, xmlNsPtr ns) { | 
807  | 0  |     if (node == NULL) { | 
808  |  | #ifdef DEBUG_TREE  | 
809  |  |         xmlGenericError(xmlGenericErrorContext,  | 
810  |  |     "xmlSetNs: node == NULL\n");  | 
811  |  | #endif  | 
812  | 0  |   return;  | 
813  | 0  |     }  | 
814  | 0  |     if ((node->type == XML_ELEMENT_NODE) ||  | 
815  | 0  |         (node->type == XML_ATTRIBUTE_NODE))  | 
816  | 0  |   node->ns = ns;  | 
817  | 0  | }  | 
818  |  |  | 
819  |  | /**  | 
820  |  |  * xmlFreeNs:  | 
821  |  |  * @cur:  the namespace pointer  | 
822  |  |  *  | 
823  |  |  * Free up the structures associated to a namespace  | 
824  |  |  */  | 
825  |  | void  | 
826  | 413k  | xmlFreeNs(xmlNsPtr cur) { | 
827  | 413k  |     if (cur == NULL) { | 
828  |  | #ifdef DEBUG_TREE  | 
829  |  |         xmlGenericError(xmlGenericErrorContext,  | 
830  |  |     "xmlFreeNs : ns == NULL\n");  | 
831  |  | #endif  | 
832  | 0  |   return;  | 
833  | 0  |     }  | 
834  | 413k  |     if (cur->href != NULL) xmlFree((char *) cur->href);  | 
835  | 413k  |     if (cur->prefix != NULL) xmlFree((char *) cur->prefix);  | 
836  | 413k  |     xmlFree(cur);  | 
837  | 413k  | }  | 
838  |  |  | 
839  |  | /**  | 
840  |  |  * xmlFreeNsList:  | 
841  |  |  * @cur:  the first namespace pointer  | 
842  |  |  *  | 
843  |  |  * Free up all the structures associated to the chained namespaces.  | 
844  |  |  */  | 
845  |  | void  | 
846  | 413k  | xmlFreeNsList(xmlNsPtr cur) { | 
847  | 413k  |     xmlNsPtr next;  | 
848  | 413k  |     if (cur == NULL) { | 
849  |  | #ifdef DEBUG_TREE  | 
850  |  |         xmlGenericError(xmlGenericErrorContext,  | 
851  |  |     "xmlFreeNsList : ns == NULL\n");  | 
852  |  | #endif  | 
853  | 0  |   return;  | 
854  | 0  |     }  | 
855  | 826k  |     while (cur != NULL) { | 
856  | 413k  |         next = cur->next;  | 
857  | 413k  |         xmlFreeNs(cur);  | 
858  | 413k  |   cur = next;  | 
859  | 413k  |     }  | 
860  | 413k  | }  | 
861  |  |  | 
862  |  | /**  | 
863  |  |  * xmlNewDtd:  | 
864  |  |  * @doc:  the document pointer  | 
865  |  |  * @name:  the DTD name  | 
866  |  |  * @ExternalID:  the external ID  | 
867  |  |  * @SystemID:  the system ID  | 
868  |  |  *  | 
869  |  |  * Creation of a new DTD for the external subset. To create an  | 
870  |  |  * internal subset, use xmlCreateIntSubset().  | 
871  |  |  *  | 
872  |  |  * Returns a pointer to the new DTD structure  | 
873  |  |  */  | 
874  |  | xmlDtdPtr  | 
875  |  | xmlNewDtd(xmlDocPtr doc, const xmlChar *name,  | 
876  | 0  |                     const xmlChar *ExternalID, const xmlChar *SystemID) { | 
877  | 0  |     xmlDtdPtr cur;  | 
878  |  | 
  | 
879  | 0  |     if ((doc != NULL) && (doc->extSubset != NULL)) { | 
880  |  | #ifdef DEBUG_TREE  | 
881  |  |         xmlGenericError(xmlGenericErrorContext,  | 
882  |  |     "xmlNewDtd(%s): document %s already have a DTD %s\n",  | 
883  |  |       /* !!! */ (char *) name, doc->name,  | 
884  |  |       /* !!! */ (char *)doc->extSubset->name);  | 
885  |  | #endif  | 
886  | 0  |   return(NULL);  | 
887  | 0  |     }  | 
888  |  |  | 
889  |  |     /*  | 
890  |  |      * Allocate a new DTD and fill the fields.  | 
891  |  |      */  | 
892  | 0  |     cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));  | 
893  | 0  |     if (cur == NULL) { | 
894  | 0  |   xmlTreeErrMemory("building DTD"); | 
895  | 0  |   return(NULL);  | 
896  | 0  |     }  | 
897  | 0  |     memset(cur, 0 , sizeof(xmlDtd));  | 
898  | 0  |     cur->type = XML_DTD_NODE;  | 
899  |  | 
  | 
900  | 0  |     if (name != NULL)  | 
901  | 0  |   cur->name = xmlStrdup(name);  | 
902  | 0  |     if (ExternalID != NULL)  | 
903  | 0  |   cur->ExternalID = xmlStrdup(ExternalID);  | 
904  | 0  |     if (SystemID != NULL)  | 
905  | 0  |   cur->SystemID = xmlStrdup(SystemID);  | 
906  | 0  |     if (doc != NULL)  | 
907  | 0  |   doc->extSubset = cur;  | 
908  | 0  |     cur->doc = doc;  | 
909  |  | 
  | 
910  | 0  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
911  | 0  |   xmlRegisterNodeDefaultValue((xmlNodePtr)cur);  | 
912  | 0  |     return(cur);  | 
913  | 0  | }  | 
914  |  |  | 
915  |  | /**  | 
916  |  |  * xmlGetIntSubset:  | 
917  |  |  * @doc:  the document pointer  | 
918  |  |  *  | 
919  |  |  * Get the internal subset of a document  | 
920  |  |  * Returns a pointer to the DTD structure or NULL if not found  | 
921  |  |  */  | 
922  |  |  | 
923  |  | xmlDtdPtr  | 
924  | 0  | xmlGetIntSubset(const xmlDoc *doc) { | 
925  | 0  |     xmlNodePtr cur;  | 
926  |  | 
  | 
927  | 0  |     if (doc == NULL)  | 
928  | 0  |   return(NULL);  | 
929  | 0  |     cur = doc->children;  | 
930  | 0  |     while (cur != NULL) { | 
931  | 0  |   if (cur->type == XML_DTD_NODE)  | 
932  | 0  |       return((xmlDtdPtr) cur);  | 
933  | 0  |   cur = cur->next;  | 
934  | 0  |     }  | 
935  | 0  |     return((xmlDtdPtr) doc->intSubset);  | 
936  | 0  | }  | 
937  |  |  | 
938  |  | /**  | 
939  |  |  * xmlCreateIntSubset:  | 
940  |  |  * @doc:  the document pointer  | 
941  |  |  * @name:  the DTD name  | 
942  |  |  * @ExternalID:  the external (PUBLIC) ID  | 
943  |  |  * @SystemID:  the system ID  | 
944  |  |  *  | 
945  |  |  * Create the internal subset of a document  | 
946  |  |  * Returns a pointer to the new DTD structure  | 
947  |  |  */  | 
948  |  | xmlDtdPtr  | 
949  |  | xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,  | 
950  | 0  |                    const xmlChar *ExternalID, const xmlChar *SystemID) { | 
951  | 0  |     xmlDtdPtr cur;  | 
952  |  | 
  | 
953  | 0  |     if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) { | 
954  |  | #ifdef DEBUG_TREE  | 
955  |  |         xmlGenericError(xmlGenericErrorContext,  | 
956  |  |  | 
957  |  |      "xmlCreateIntSubset(): document %s already have an internal subset\n",  | 
958  |  |       doc->name);  | 
959  |  | #endif  | 
960  | 0  |   return(NULL);  | 
961  | 0  |     }  | 
962  |  |  | 
963  |  |     /*  | 
964  |  |      * Allocate a new DTD and fill the fields.  | 
965  |  |      */  | 
966  | 0  |     cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));  | 
967  | 0  |     if (cur == NULL) { | 
968  | 0  |   xmlTreeErrMemory("building internal subset"); | 
969  | 0  |   return(NULL);  | 
970  | 0  |     }  | 
971  | 0  |     memset(cur, 0, sizeof(xmlDtd));  | 
972  | 0  |     cur->type = XML_DTD_NODE;  | 
973  |  | 
  | 
974  | 0  |     if (name != NULL) { | 
975  | 0  |   cur->name = xmlStrdup(name);  | 
976  | 0  |   if (cur->name == NULL) { | 
977  | 0  |       xmlTreeErrMemory("building internal subset"); | 
978  | 0  |       xmlFree(cur);  | 
979  | 0  |       return(NULL);  | 
980  | 0  |   }  | 
981  | 0  |     }  | 
982  | 0  |     if (ExternalID != NULL) { | 
983  | 0  |   cur->ExternalID = xmlStrdup(ExternalID);  | 
984  | 0  |   if (cur->ExternalID  == NULL) { | 
985  | 0  |       xmlTreeErrMemory("building internal subset"); | 
986  | 0  |       if (cur->name != NULL)  | 
987  | 0  |           xmlFree((char *)cur->name);  | 
988  | 0  |       xmlFree(cur);  | 
989  | 0  |       return(NULL);  | 
990  | 0  |   }  | 
991  | 0  |     }  | 
992  | 0  |     if (SystemID != NULL) { | 
993  | 0  |   cur->SystemID = xmlStrdup(SystemID);  | 
994  | 0  |   if (cur->SystemID == NULL) { | 
995  | 0  |       xmlTreeErrMemory("building internal subset"); | 
996  | 0  |       if (cur->name != NULL)  | 
997  | 0  |           xmlFree((char *)cur->name);  | 
998  | 0  |       if (cur->ExternalID != NULL)  | 
999  | 0  |           xmlFree((char *)cur->ExternalID);  | 
1000  | 0  |       xmlFree(cur);  | 
1001  | 0  |       return(NULL);  | 
1002  | 0  |   }  | 
1003  | 0  |     }  | 
1004  | 0  |     if (doc != NULL) { | 
1005  | 0  |   doc->intSubset = cur;  | 
1006  | 0  |   cur->parent = doc;  | 
1007  | 0  |   cur->doc = doc;  | 
1008  | 0  |   if (doc->children == NULL) { | 
1009  | 0  |       doc->children = (xmlNodePtr) cur;  | 
1010  | 0  |       doc->last = (xmlNodePtr) cur;  | 
1011  | 0  |   } else { | 
1012  | 0  |       if (doc->type == XML_HTML_DOCUMENT_NODE) { | 
1013  | 0  |     xmlNodePtr prev;  | 
1014  |  | 
  | 
1015  | 0  |     prev = doc->children;  | 
1016  | 0  |     prev->prev = (xmlNodePtr) cur;  | 
1017  | 0  |     cur->next = prev;  | 
1018  | 0  |     doc->children = (xmlNodePtr) cur;  | 
1019  | 0  |       } else { | 
1020  | 0  |     xmlNodePtr next;  | 
1021  |  | 
  | 
1022  | 0  |     next = doc->children;  | 
1023  | 0  |     while ((next != NULL) && (next->type != XML_ELEMENT_NODE))  | 
1024  | 0  |         next = next->next;  | 
1025  | 0  |     if (next == NULL) { | 
1026  | 0  |         cur->prev = doc->last;  | 
1027  | 0  |         cur->prev->next = (xmlNodePtr) cur;  | 
1028  | 0  |         cur->next = NULL;  | 
1029  | 0  |         doc->last = (xmlNodePtr) cur;  | 
1030  | 0  |     } else { | 
1031  | 0  |         cur->next = next;  | 
1032  | 0  |         cur->prev = next->prev;  | 
1033  | 0  |         if (cur->prev == NULL)  | 
1034  | 0  |       doc->children = (xmlNodePtr) cur;  | 
1035  | 0  |         else  | 
1036  | 0  |       cur->prev->next = (xmlNodePtr) cur;  | 
1037  | 0  |         next->prev = (xmlNodePtr) cur;  | 
1038  | 0  |     }  | 
1039  | 0  |       }  | 
1040  | 0  |   }  | 
1041  | 0  |     }  | 
1042  |  | 
  | 
1043  | 0  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
1044  | 0  |   xmlRegisterNodeDefaultValue((xmlNodePtr)cur);  | 
1045  | 0  |     return(cur);  | 
1046  | 0  | }  | 
1047  |  |  | 
1048  |  | /**  | 
1049  |  |  * DICT_FREE:  | 
1050  |  |  * @str:  a string  | 
1051  |  |  *  | 
1052  |  |  * Free a string if it is not owned by the "dict" dictionary in the  | 
1053  |  |  * current scope  | 
1054  |  |  */  | 
1055  |  | #define DICT_FREE(str)            \  | 
1056  | 9.35M  |   if ((str) && ((!dict) ||       \  | 
1057  | 8.37M  |       (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \  | 
1058  | 4.68M  |       xmlFree((char *)(str));  | 
1059  |  |  | 
1060  |  |  | 
1061  |  | /**  | 
1062  |  |  * DICT_COPY:  | 
1063  |  |  * @str:  a string  | 
1064  |  |  *  | 
1065  |  |  * Copy a string using a "dict" dictionary in the current scope,  | 
1066  |  |  * if available.  | 
1067  |  |  */  | 
1068  |  | #define DICT_COPY(str, cpy) \  | 
1069  | 0  |     if (str) { \ | 
1070  | 0  |   if (dict) { \ | 
1071  | 0  |       if (xmlDictOwns(dict, (const xmlChar *)(str))) \  | 
1072  | 0  |     cpy = (xmlChar *) (str); \  | 
1073  | 0  |       else \  | 
1074  | 0  |     cpy = (xmlChar *) xmlDictLookup((dict), (const xmlChar *)(str), -1); \  | 
1075  | 0  |   } else \  | 
1076  | 0  |       cpy = xmlStrdup((const xmlChar *)(str)); }  | 
1077  |  |  | 
1078  |  | /**  | 
1079  |  |  * DICT_CONST_COPY:  | 
1080  |  |  * @str:  a string  | 
1081  |  |  *  | 
1082  |  |  * Copy a string using a "dict" dictionary in the current scope,  | 
1083  |  |  * if available.  | 
1084  |  |  */  | 
1085  |  | #define DICT_CONST_COPY(str, cpy) \  | 
1086  | 0  |     if (str) { \ | 
1087  | 0  |   if (dict) { \ | 
1088  | 0  |       if (xmlDictOwns(dict, (const xmlChar *)(str))) \  | 
1089  | 0  |     cpy = (const xmlChar *) (str); \  | 
1090  | 0  |       else \  | 
1091  | 0  |     cpy = xmlDictLookup((dict), (const xmlChar *)(str), -1); \  | 
1092  | 0  |   } else \  | 
1093  | 0  |       cpy = (const xmlChar *) xmlStrdup((const xmlChar *)(str)); }  | 
1094  |  |  | 
1095  |  |  | 
1096  |  | /**  | 
1097  |  |  * xmlFreeDtd:  | 
1098  |  |  * @cur:  the DTD structure to free up  | 
1099  |  |  *  | 
1100  |  |  * Free a DTD structure.  | 
1101  |  |  */  | 
1102  |  | void  | 
1103  | 0  | xmlFreeDtd(xmlDtdPtr cur) { | 
1104  | 0  |     xmlDictPtr dict = NULL;  | 
1105  |  | 
  | 
1106  | 0  |     if (cur == NULL) { | 
1107  | 0  |   return;  | 
1108  | 0  |     }  | 
1109  | 0  |     if (cur->doc != NULL) dict = cur->doc->dict;  | 
1110  |  | 
  | 
1111  | 0  |     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))  | 
1112  | 0  |   xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);  | 
1113  |  | 
  | 
1114  | 0  |     if (cur->children != NULL) { | 
1115  | 0  |   xmlNodePtr next, c = cur->children;  | 
1116  |  |  | 
1117  |  |   /*  | 
1118  |  |    * Cleanup all nodes which are not part of the specific lists  | 
1119  |  |    * of notations, elements, attributes and entities.  | 
1120  |  |    */  | 
1121  | 0  |         while (c != NULL) { | 
1122  | 0  |       next = c->next;  | 
1123  | 0  |       if ((c->type != XML_NOTATION_NODE) &&  | 
1124  | 0  |           (c->type != XML_ELEMENT_DECL) &&  | 
1125  | 0  |     (c->type != XML_ATTRIBUTE_DECL) &&  | 
1126  | 0  |     (c->type != XML_ENTITY_DECL)) { | 
1127  | 0  |     xmlUnlinkNode(c);  | 
1128  | 0  |     xmlFreeNode(c);  | 
1129  | 0  |       }  | 
1130  | 0  |       c = next;  | 
1131  | 0  |   }  | 
1132  | 0  |     }  | 
1133  | 0  |     DICT_FREE(cur->name)  | 
1134  | 0  |     DICT_FREE(cur->SystemID)  | 
1135  | 0  |     DICT_FREE(cur->ExternalID)  | 
1136  |  |     /* TODO !!! */  | 
1137  | 0  |     if (cur->notations != NULL)  | 
1138  | 0  |         xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);  | 
1139  |  | 
  | 
1140  | 0  |     if (cur->elements != NULL)  | 
1141  | 0  |         xmlFreeElementTable((xmlElementTablePtr) cur->elements);  | 
1142  | 0  |     if (cur->attributes != NULL)  | 
1143  | 0  |         xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);  | 
1144  | 0  |     if (cur->entities != NULL)  | 
1145  | 0  |         xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);  | 
1146  | 0  |     if (cur->pentities != NULL)  | 
1147  | 0  |         xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->pentities);  | 
1148  |  | 
  | 
1149  | 0  |     xmlFree(cur);  | 
1150  | 0  | }  | 
1151  |  |  | 
1152  |  | /**  | 
1153  |  |  * xmlNewDoc:  | 
1154  |  |  * @version:  xmlChar string giving the version of XML "1.0"  | 
1155  |  |  *  | 
1156  |  |  * Creates a new XML document  | 
1157  |  |  *  | 
1158  |  |  * Returns a new document  | 
1159  |  |  */  | 
1160  |  | xmlDocPtr  | 
1161  | 497k  | xmlNewDoc(const xmlChar *version) { | 
1162  | 497k  |     xmlDocPtr cur;  | 
1163  |  |  | 
1164  | 497k  |     if (version == NULL)  | 
1165  | 493k  |   version = (const xmlChar *) "1.0";  | 
1166  |  |  | 
1167  |  |     /*  | 
1168  |  |      * Allocate a new document and fill the fields.  | 
1169  |  |      */  | 
1170  | 497k  |     cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));  | 
1171  | 497k  |     if (cur == NULL) { | 
1172  | 0  |   xmlTreeErrMemory("building doc"); | 
1173  | 0  |   return(NULL);  | 
1174  | 0  |     }  | 
1175  | 497k  |     memset(cur, 0, sizeof(xmlDoc));  | 
1176  | 497k  |     cur->type = XML_DOCUMENT_NODE;  | 
1177  |  |  | 
1178  | 497k  |     cur->version = xmlStrdup(version);  | 
1179  | 497k  |     if (cur->version == NULL) { | 
1180  | 0  |   xmlTreeErrMemory("building doc"); | 
1181  | 0  |   xmlFree(cur);  | 
1182  | 0  |   return(NULL);  | 
1183  | 0  |     }  | 
1184  | 497k  |     cur->standalone = -1;  | 
1185  | 497k  |     cur->compression = -1; /* not initialized */  | 
1186  | 497k  |     cur->doc = cur;  | 
1187  | 497k  |     cur->parseFlags = 0;  | 
1188  | 497k  |     cur->properties = XML_DOC_USERBUILT;  | 
1189  |  |     /*  | 
1190  |  |      * The in memory encoding is always UTF8  | 
1191  |  |      * This field will never change and would  | 
1192  |  |      * be obsolete if not for binary compatibility.  | 
1193  |  |      */  | 
1194  | 497k  |     cur->charset = XML_CHAR_ENCODING_UTF8;  | 
1195  |  |  | 
1196  | 497k  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
1197  | 0  |   xmlRegisterNodeDefaultValue((xmlNodePtr)cur);  | 
1198  | 497k  |     return(cur);  | 
1199  | 497k  | }  | 
1200  |  |  | 
1201  |  | /**  | 
1202  |  |  * xmlFreeDoc:  | 
1203  |  |  * @cur:  pointer to the document  | 
1204  |  |  *  | 
1205  |  |  * Free up all the structures used by a document, tree included.  | 
1206  |  |  */  | 
1207  |  | void  | 
1208  | 493k  | xmlFreeDoc(xmlDocPtr cur) { | 
1209  | 493k  |     xmlDtdPtr extSubset, intSubset;  | 
1210  | 493k  |     xmlDictPtr dict = NULL;  | 
1211  |  |  | 
1212  | 493k  |     if (cur == NULL) { | 
1213  |  | #ifdef DEBUG_TREE  | 
1214  |  |         xmlGenericError(xmlGenericErrorContext,  | 
1215  |  |     "xmlFreeDoc : document == NULL\n");  | 
1216  |  | #endif  | 
1217  | 0  |   return;  | 
1218  | 0  |     }  | 
1219  |  |  | 
1220  | 493k  |     if (cur != NULL) dict = cur->dict;  | 
1221  |  |  | 
1222  | 493k  |     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))  | 
1223  | 0  |   xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);  | 
1224  |  |  | 
1225  |  |     /*  | 
1226  |  |      * Do this before freeing the children list to avoid ID lookups  | 
1227  |  |      */  | 
1228  | 493k  |     if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);  | 
1229  | 493k  |     cur->ids = NULL;  | 
1230  | 493k  |     if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);  | 
1231  | 493k  |     cur->refs = NULL;  | 
1232  | 493k  |     extSubset = cur->extSubset;  | 
1233  | 493k  |     intSubset = cur->intSubset;  | 
1234  | 493k  |     if (intSubset == extSubset)  | 
1235  | 493k  |   extSubset = NULL;  | 
1236  | 493k  |     if (extSubset != NULL) { | 
1237  | 0  |   xmlUnlinkNode((xmlNodePtr) cur->extSubset);  | 
1238  | 0  |   cur->extSubset = NULL;  | 
1239  | 0  |   xmlFreeDtd(extSubset);  | 
1240  | 0  |     }  | 
1241  | 493k  |     if (intSubset != NULL) { | 
1242  | 0  |   xmlUnlinkNode((xmlNodePtr) cur->intSubset);  | 
1243  | 0  |   cur->intSubset = NULL;  | 
1244  | 0  |   xmlFreeDtd(intSubset);  | 
1245  | 0  |     }  | 
1246  |  |  | 
1247  | 493k  |     if (cur->children != NULL) xmlFreeNodeList(cur->children);  | 
1248  | 493k  |     if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);  | 
1249  |  |  | 
1250  | 493k  |     DICT_FREE(cur->version)  | 
1251  | 493k  |     DICT_FREE(cur->name)  | 
1252  | 493k  |     DICT_FREE(cur->encoding)  | 
1253  | 493k  |     DICT_FREE(cur->URL)  | 
1254  | 493k  |     xmlFree(cur);  | 
1255  | 493k  |     if (dict) xmlDictFree(dict);  | 
1256  | 493k  | }  | 
1257  |  |  | 
1258  |  | /**  | 
1259  |  |  * xmlStringLenGetNodeList:  | 
1260  |  |  * @doc:  the document  | 
1261  |  |  * @value:  the value of the text  | 
1262  |  |  * @len:  the length of the string value  | 
1263  |  |  *  | 
1264  |  |  * Parse the value string and build the node list associated. Should  | 
1265  |  |  * produce a flat tree with only TEXTs and ENTITY_REFs.  | 
1266  |  |  * Returns a pointer to the first child  | 
1267  |  |  */  | 
1268  |  | xmlNodePtr  | 
1269  | 3.70k  | xmlStringLenGetNodeList(const xmlDoc *doc, const xmlChar *value, int len) { | 
1270  | 3.70k  |     xmlNodePtr ret = NULL, last = NULL;  | 
1271  | 3.70k  |     xmlNodePtr node;  | 
1272  | 3.70k  |     xmlChar *val;  | 
1273  | 3.70k  |     const xmlChar *cur, *end;  | 
1274  | 3.70k  |     const xmlChar *q;  | 
1275  | 3.70k  |     xmlEntityPtr ent;  | 
1276  | 3.70k  |     xmlBufPtr buf;  | 
1277  |  |  | 
1278  | 3.70k  |     if (value == NULL) return(NULL);  | 
1279  | 3.70k  |     cur = value;  | 
1280  | 3.70k  |     end = cur + len;  | 
1281  |  |  | 
1282  | 3.70k  |     buf = xmlBufCreateSize(0);  | 
1283  | 3.70k  |     if (buf == NULL) return(NULL);  | 
1284  | 3.70k  |     xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);  | 
1285  |  |  | 
1286  | 3.70k  |     q = cur;  | 
1287  | 25.9k  |     while ((cur < end) && (*cur != 0)) { | 
1288  | 22.2k  |   if (cur[0] == '&') { | 
1289  | 0  |       int charval = 0;  | 
1290  | 0  |       xmlChar tmp;  | 
1291  |  |  | 
1292  |  |       /*  | 
1293  |  |        * Save the current text.  | 
1294  |  |        */  | 
1295  | 0  |             if (cur != q) { | 
1296  | 0  |     if (xmlBufAdd(buf, q, cur - q))  | 
1297  | 0  |         goto out;  | 
1298  | 0  |       }  | 
1299  | 0  |       q = cur;  | 
1300  | 0  |       if ((cur + 2 < end) && (cur[1] == '#') && (cur[2] == 'x')) { | 
1301  | 0  |     cur += 3;  | 
1302  | 0  |     if (cur < end)  | 
1303  | 0  |         tmp = *cur;  | 
1304  | 0  |     else  | 
1305  | 0  |         tmp = 0;  | 
1306  | 0  |     while (tmp != ';') { /* Non input consuming loop */ | 
1307  |  |                     /*  | 
1308  |  |                      * If you find an integer overflow here when fuzzing,  | 
1309  |  |                      * the bug is probably elsewhere. This function should  | 
1310  |  |                      * only receive entities that were already validated by  | 
1311  |  |                      * the parser, typically by xmlParseAttValueComplex  | 
1312  |  |                      * calling xmlStringDecodeEntities.  | 
1313  |  |                      *  | 
1314  |  |                      * So it's better *not* to check for overflow to  | 
1315  |  |                      * potentially discover new bugs.  | 
1316  |  |                      */  | 
1317  | 0  |         if ((tmp >= '0') && (tmp <= '9'))  | 
1318  | 0  |       charval = charval * 16 + (tmp - '0');  | 
1319  | 0  |         else if ((tmp >= 'a') && (tmp <= 'f'))  | 
1320  | 0  |       charval = charval * 16 + (tmp - 'a') + 10;  | 
1321  | 0  |         else if ((tmp >= 'A') && (tmp <= 'F'))  | 
1322  | 0  |       charval = charval * 16 + (tmp - 'A') + 10;  | 
1323  | 0  |         else { | 
1324  | 0  |       xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,  | 
1325  | 0  |                  NULL);  | 
1326  | 0  |       charval = 0;  | 
1327  | 0  |       break;  | 
1328  | 0  |         }  | 
1329  | 0  |         cur++;  | 
1330  | 0  |         if (cur < end)  | 
1331  | 0  |       tmp = *cur;  | 
1332  | 0  |         else  | 
1333  | 0  |       tmp = 0;  | 
1334  | 0  |     }  | 
1335  | 0  |     if (tmp == ';')  | 
1336  | 0  |         cur++;  | 
1337  | 0  |     q = cur;  | 
1338  | 0  |       } else if ((cur + 1 < end) && (cur[1] == '#')) { | 
1339  | 0  |     cur += 2;  | 
1340  | 0  |     if (cur < end)  | 
1341  | 0  |         tmp = *cur;  | 
1342  | 0  |     else  | 
1343  | 0  |         tmp = 0;  | 
1344  | 0  |     while (tmp != ';') { /* Non input consuming loops */ | 
1345  |  |                     /* Don't check for integer overflow, see above. */  | 
1346  | 0  |         if ((tmp >= '0') && (tmp <= '9'))  | 
1347  | 0  |       charval = charval * 10 + (tmp - '0');  | 
1348  | 0  |         else { | 
1349  | 0  |       xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,  | 
1350  | 0  |                  NULL);  | 
1351  | 0  |       charval = 0;  | 
1352  | 0  |       break;  | 
1353  | 0  |         }  | 
1354  | 0  |         cur++;  | 
1355  | 0  |         if (cur < end)  | 
1356  | 0  |       tmp = *cur;  | 
1357  | 0  |         else  | 
1358  | 0  |       tmp = 0;  | 
1359  | 0  |     }  | 
1360  | 0  |     if (tmp == ';')  | 
1361  | 0  |         cur++;  | 
1362  | 0  |     q = cur;  | 
1363  | 0  |       } else { | 
1364  |  |     /*  | 
1365  |  |      * Read the entity string  | 
1366  |  |      */  | 
1367  | 0  |     cur++;  | 
1368  | 0  |     q = cur;  | 
1369  | 0  |     while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++;  | 
1370  | 0  |     if ((cur >= end) || (*cur == 0)) { | 
1371  | 0  |         xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, (xmlNodePtr) doc,  | 
1372  | 0  |                    (const char *) q);  | 
1373  | 0  |         goto out;  | 
1374  | 0  |     }  | 
1375  | 0  |     if (cur != q) { | 
1376  |  |         /*  | 
1377  |  |          * Predefined entities don't generate nodes  | 
1378  |  |          */  | 
1379  | 0  |         val = xmlStrndup(q, cur - q);  | 
1380  | 0  |         ent = xmlGetDocEntity(doc, val);  | 
1381  | 0  |         if ((ent != NULL) &&  | 
1382  | 0  |       (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { | 
1383  |  | 
  | 
1384  | 0  |       if (xmlBufCat(buf, ent->content))  | 
1385  | 0  |           goto out;  | 
1386  |  | 
  | 
1387  | 0  |         } else { | 
1388  |  |       /*  | 
1389  |  |        * Flush buffer so far  | 
1390  |  |        */  | 
1391  | 0  |       if (!xmlBufIsEmpty(buf)) { | 
1392  | 0  |           node = xmlNewDocText(doc, NULL);  | 
1393  | 0  |           if (node == NULL) { | 
1394  | 0  |         if (val != NULL) xmlFree(val);  | 
1395  | 0  |         goto out;  | 
1396  | 0  |           }  | 
1397  | 0  |           node->content = xmlBufDetach(buf);  | 
1398  |  | 
  | 
1399  | 0  |           if (last == NULL) { | 
1400  | 0  |         last = ret = node;  | 
1401  | 0  |           } else { | 
1402  | 0  |         last = xmlAddNextSibling(last, node);  | 
1403  | 0  |           }  | 
1404  | 0  |       }  | 
1405  |  |  | 
1406  |  |       /*  | 
1407  |  |        * Create a new REFERENCE_REF node  | 
1408  |  |        */  | 
1409  | 0  |       node = xmlNewReference(doc, val);  | 
1410  | 0  |       if (node == NULL) { | 
1411  | 0  |           if (val != NULL) xmlFree(val);  | 
1412  | 0  |           goto out;  | 
1413  | 0  |       }  | 
1414  | 0  |       else if ((ent != NULL) &&  | 
1415  | 0  |                                  ((ent->flags & XML_ENT_PARSED) == 0) &&  | 
1416  | 0  |                                  ((ent->flags & XML_ENT_EXPANDING) == 0)) { | 
1417  | 0  |           xmlNodePtr temp;  | 
1418  |  |  | 
1419  |  |                             /*  | 
1420  |  |                              * The entity should have been checked already,  | 
1421  |  |                              * but set the flag anyway to avoid recursion.  | 
1422  |  |                              */  | 
1423  | 0  |           ent->flags |= XML_ENT_EXPANDING;  | 
1424  | 0  |           ent->children = xmlStringGetNodeList(doc,  | 
1425  | 0  |             (const xmlChar*)node->content);  | 
1426  | 0  |           ent->owner = 1;  | 
1427  | 0  |           ent->flags &= ~XML_ENT_EXPANDING;  | 
1428  | 0  |                             ent->flags |= XML_ENT_PARSED;  | 
1429  | 0  |           temp = ent->children;  | 
1430  | 0  |           while (temp) { | 
1431  | 0  |         temp->parent = (xmlNodePtr)ent;  | 
1432  | 0  |         ent->last = temp;  | 
1433  | 0  |         temp = temp->next;  | 
1434  | 0  |           }  | 
1435  | 0  |       }  | 
1436  | 0  |       if (last == NULL) { | 
1437  | 0  |           last = ret = node;  | 
1438  | 0  |       } else { | 
1439  | 0  |           last = xmlAddNextSibling(last, node);  | 
1440  | 0  |       }  | 
1441  | 0  |         }  | 
1442  | 0  |         xmlFree(val);  | 
1443  | 0  |     }  | 
1444  | 0  |     cur++;  | 
1445  | 0  |     q = cur;  | 
1446  | 0  |       }  | 
1447  | 0  |       if (charval != 0) { | 
1448  | 0  |     xmlChar buffer[10];  | 
1449  | 0  |     int l;  | 
1450  |  | 
  | 
1451  | 0  |     l = xmlCopyCharMultiByte(buffer, charval);  | 
1452  | 0  |     buffer[l] = 0;  | 
1453  |  | 
  | 
1454  | 0  |     if (xmlBufCat(buf, buffer))  | 
1455  | 0  |         goto out;  | 
1456  | 0  |     charval = 0;  | 
1457  | 0  |       }  | 
1458  | 0  |   } else  | 
1459  | 22.2k  |       cur++;  | 
1460  | 22.2k  |     }  | 
1461  |  |  | 
1462  | 3.70k  |     if (cur != q) { | 
1463  |  |         /*  | 
1464  |  |    * Handle the last piece of text.  | 
1465  |  |    */  | 
1466  | 3.70k  |   if (xmlBufAdd(buf, q, cur - q))  | 
1467  | 0  |       goto out;  | 
1468  | 3.70k  |     }  | 
1469  |  |  | 
1470  | 3.70k  |     if (!xmlBufIsEmpty(buf)) { | 
1471  | 3.70k  |   node = xmlNewDocText(doc, NULL);  | 
1472  | 3.70k  |   if (node == NULL) goto out;  | 
1473  | 3.70k  |   node->content = xmlBufDetach(buf);  | 
1474  |  |  | 
1475  | 3.70k  |   if (last == NULL) { | 
1476  | 3.70k  |       ret = node;  | 
1477  | 3.70k  |   } else { | 
1478  | 0  |       xmlAddNextSibling(last, node);  | 
1479  | 0  |   }  | 
1480  | 3.70k  |     } else if (ret == NULL) { | 
1481  | 0  |         ret = xmlNewDocText(doc, BAD_CAST "");  | 
1482  | 0  |     }  | 
1483  |  |  | 
1484  | 3.70k  | out:  | 
1485  | 3.70k  |     xmlBufFree(buf);  | 
1486  | 3.70k  |     return(ret);  | 
1487  | 3.70k  | }  | 
1488  |  |  | 
1489  |  | /**  | 
1490  |  |  * xmlStringGetNodeList:  | 
1491  |  |  * @doc:  the document  | 
1492  |  |  * @value:  the value of the attribute  | 
1493  |  |  *  | 
1494  |  |  * Parse the value string and build the node list associated. Should  | 
1495  |  |  * produce a flat tree with only TEXTs and ENTITY_REFs.  | 
1496  |  |  * Returns a pointer to the first child  | 
1497  |  |  */  | 
1498  |  | xmlNodePtr  | 
1499  | 0  | xmlStringGetNodeList(const xmlDoc *doc, const xmlChar *value) { | 
1500  | 0  |     xmlNodePtr ret = NULL, head = NULL, last = NULL;  | 
1501  | 0  |     xmlNodePtr node;  | 
1502  | 0  |     xmlChar *val = NULL;  | 
1503  | 0  |     const xmlChar *cur = value;  | 
1504  | 0  |     const xmlChar *q;  | 
1505  | 0  |     xmlEntityPtr ent;  | 
1506  | 0  |     xmlBufPtr buf;  | 
1507  |  | 
  | 
1508  | 0  |     if (value == NULL) return(NULL);  | 
1509  |  |  | 
1510  | 0  |     buf = xmlBufCreateSize(0);  | 
1511  | 0  |     if (buf == NULL) return(NULL);  | 
1512  | 0  |     xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);  | 
1513  |  | 
  | 
1514  | 0  |     q = cur;  | 
1515  | 0  |     while (*cur != 0) { | 
1516  | 0  |   if (cur[0] == '&') { | 
1517  | 0  |       int charval = 0;  | 
1518  | 0  |       xmlChar tmp;  | 
1519  |  |  | 
1520  |  |       /*  | 
1521  |  |        * Save the current text.  | 
1522  |  |        */  | 
1523  | 0  |             if (cur != q) { | 
1524  | 0  |     if (xmlBufAdd(buf, q, cur - q))  | 
1525  | 0  |         goto out;  | 
1526  | 0  |       }  | 
1527  | 0  |       q = cur;  | 
1528  | 0  |       if ((cur[1] == '#') && (cur[2] == 'x')) { | 
1529  | 0  |     cur += 3;  | 
1530  | 0  |     tmp = *cur;  | 
1531  | 0  |     while (tmp != ';') { /* Non input consuming loop */ | 
1532  |  |                     /* Don't check for integer overflow, see above. */  | 
1533  | 0  |         if ((tmp >= '0') && (tmp <= '9'))  | 
1534  | 0  |       charval = charval * 16 + (tmp - '0');  | 
1535  | 0  |         else if ((tmp >= 'a') && (tmp <= 'f'))  | 
1536  | 0  |       charval = charval * 16 + (tmp - 'a') + 10;  | 
1537  | 0  |         else if ((tmp >= 'A') && (tmp <= 'F'))  | 
1538  | 0  |       charval = charval * 16 + (tmp - 'A') + 10;  | 
1539  | 0  |         else { | 
1540  | 0  |       xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,  | 
1541  | 0  |                  NULL);  | 
1542  | 0  |       charval = 0;  | 
1543  | 0  |       break;  | 
1544  | 0  |         }  | 
1545  | 0  |         cur++;  | 
1546  | 0  |         tmp = *cur;  | 
1547  | 0  |     }  | 
1548  | 0  |     if (tmp == ';')  | 
1549  | 0  |         cur++;  | 
1550  | 0  |     q = cur;  | 
1551  | 0  |       } else if  (cur[1] == '#') { | 
1552  | 0  |     cur += 2;  | 
1553  | 0  |     tmp = *cur;  | 
1554  | 0  |     while (tmp != ';') { /* Non input consuming loops */ | 
1555  |  |                     /* Don't check for integer overflow, see above. */  | 
1556  | 0  |         if ((tmp >= '0') && (tmp <= '9'))  | 
1557  | 0  |       charval = charval * 10 + (tmp - '0');  | 
1558  | 0  |         else { | 
1559  | 0  |       xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,  | 
1560  | 0  |                  NULL);  | 
1561  | 0  |       charval = 0;  | 
1562  | 0  |       break;  | 
1563  | 0  |         }  | 
1564  | 0  |         cur++;  | 
1565  | 0  |         tmp = *cur;  | 
1566  | 0  |     }  | 
1567  | 0  |     if (tmp == ';')  | 
1568  | 0  |         cur++;  | 
1569  | 0  |     q = cur;  | 
1570  | 0  |       } else { | 
1571  |  |     /*  | 
1572  |  |      * Read the entity string  | 
1573  |  |      */  | 
1574  | 0  |     cur++;  | 
1575  | 0  |     q = cur;  | 
1576  | 0  |     while ((*cur != 0) && (*cur != ';')) cur++;  | 
1577  | 0  |     if (*cur == 0) { | 
1578  | 0  |         xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY,  | 
1579  | 0  |                    (xmlNodePtr) doc, (const char *) q);  | 
1580  | 0  |         goto out;  | 
1581  | 0  |     }  | 
1582  | 0  |     if (cur != q) { | 
1583  |  |         /*  | 
1584  |  |          * Predefined entities don't generate nodes  | 
1585  |  |          */  | 
1586  | 0  |         val = xmlStrndup(q, cur - q);  | 
1587  | 0  |         ent = xmlGetDocEntity(doc, val);  | 
1588  | 0  |         if ((ent != NULL) &&  | 
1589  | 0  |       (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) { | 
1590  |  | 
  | 
1591  | 0  |       if (xmlBufCat(buf, ent->content))  | 
1592  | 0  |           goto out;  | 
1593  |  | 
  | 
1594  | 0  |         } else { | 
1595  |  |       /*  | 
1596  |  |        * Flush buffer so far  | 
1597  |  |        */  | 
1598  | 0  |       if (!xmlBufIsEmpty(buf)) { | 
1599  | 0  |           node = xmlNewDocText(doc, NULL);  | 
1600  | 0  |                             if (node == NULL)  | 
1601  | 0  |                                 goto out;  | 
1602  | 0  |           node->content = xmlBufDetach(buf);  | 
1603  |  | 
  | 
1604  | 0  |           if (last == NULL) { | 
1605  | 0  |         last = head = node;  | 
1606  | 0  |           } else { | 
1607  | 0  |         last = xmlAddNextSibling(last, node);  | 
1608  | 0  |           }  | 
1609  | 0  |       }  | 
1610  |  |  | 
1611  |  |       /*  | 
1612  |  |        * Create a new REFERENCE_REF node  | 
1613  |  |        */  | 
1614  | 0  |       node = xmlNewReference(doc, val);  | 
1615  | 0  |       if (node == NULL)  | 
1616  | 0  |           goto out;  | 
1617  | 0  |       if ((ent != NULL) &&  | 
1618  | 0  |                             ((ent->flags & XML_ENT_PARSED) == 0) &&  | 
1619  | 0  |                             ((ent->flags & XML_ENT_EXPANDING) == 0)) { | 
1620  | 0  |           xmlNodePtr temp;  | 
1621  |  |  | 
1622  |  |                             /*  | 
1623  |  |                              * The entity should have been checked already,  | 
1624  |  |                              * but set the flag anyway to avoid recursion.  | 
1625  |  |                              */  | 
1626  | 0  |           ent->flags |= XML_ENT_EXPANDING;  | 
1627  | 0  |           ent->children = xmlStringGetNodeList(doc,  | 
1628  | 0  |             (const xmlChar*)node->content);  | 
1629  | 0  |           ent->owner = 1;  | 
1630  | 0  |           ent->flags &= ~XML_ENT_EXPANDING;  | 
1631  | 0  |                             ent->flags |= XML_ENT_PARSED;  | 
1632  | 0  |           temp = ent->children;  | 
1633  | 0  |           while (temp) { | 
1634  | 0  |         temp->parent = (xmlNodePtr)ent;  | 
1635  | 0  |         ent->last = temp;  | 
1636  | 0  |         temp = temp->next;  | 
1637  | 0  |           }  | 
1638  | 0  |       }  | 
1639  | 0  |       if (last == NULL) { | 
1640  | 0  |           last = head = node;  | 
1641  | 0  |       } else { | 
1642  | 0  |           last = xmlAddNextSibling(last, node);  | 
1643  | 0  |       }  | 
1644  | 0  |         }  | 
1645  | 0  |         xmlFree(val);  | 
1646  | 0  |                     val = NULL;  | 
1647  | 0  |     }  | 
1648  | 0  |     cur++;  | 
1649  | 0  |     q = cur;  | 
1650  | 0  |       }  | 
1651  | 0  |       if (charval != 0) { | 
1652  | 0  |     xmlChar buffer[10];  | 
1653  | 0  |     int len;  | 
1654  |  | 
  | 
1655  | 0  |     len = xmlCopyCharMultiByte(buffer, charval);  | 
1656  | 0  |     buffer[len] = 0;  | 
1657  |  | 
  | 
1658  | 0  |     if (xmlBufCat(buf, buffer))  | 
1659  | 0  |         goto out;  | 
1660  | 0  |     charval = 0;  | 
1661  | 0  |       }  | 
1662  | 0  |   } else  | 
1663  | 0  |       cur++;  | 
1664  | 0  |     }  | 
1665  | 0  |     if ((cur != q) || (head == NULL)) { | 
1666  |  |         /*  | 
1667  |  |    * Handle the last piece of text.  | 
1668  |  |    */  | 
1669  | 0  |   xmlBufAdd(buf, q, cur - q);  | 
1670  | 0  |     }  | 
1671  |  | 
  | 
1672  | 0  |     if (!xmlBufIsEmpty(buf)) { | 
1673  | 0  |   node = xmlNewDocText(doc, NULL);  | 
1674  | 0  |         if (node == NULL)  | 
1675  | 0  |             goto out;  | 
1676  | 0  |   node->content = xmlBufDetach(buf);  | 
1677  |  | 
  | 
1678  | 0  |   if (last == NULL) { | 
1679  | 0  |       head = node;  | 
1680  | 0  |   } else { | 
1681  | 0  |       xmlAddNextSibling(last, node);  | 
1682  | 0  |   }  | 
1683  | 0  |     }  | 
1684  |  |  | 
1685  | 0  |     ret = head;  | 
1686  | 0  |     head = NULL;  | 
1687  |  | 
  | 
1688  | 0  | out:  | 
1689  | 0  |     xmlBufFree(buf);  | 
1690  | 0  |     if (val != NULL) xmlFree(val);  | 
1691  | 0  |     if (head != NULL) xmlFreeNodeList(head);  | 
1692  | 0  |     return(ret);  | 
1693  | 0  | }  | 
1694  |  |  | 
1695  |  | /**  | 
1696  |  |  * xmlNodeListGetString:  | 
1697  |  |  * @doc:  the document  | 
1698  |  |  * @list:  a Node list  | 
1699  |  |  * @inLine:  should we replace entity contents or show their external form  | 
1700  |  |  *  | 
1701  |  |  * Build the string equivalent to the text contained in the Node list  | 
1702  |  |  * made of TEXTs and ENTITY_REFs  | 
1703  |  |  *  | 
1704  |  |  * Returns a pointer to the string copy, the caller must free it with xmlFree().  | 
1705  |  |  */  | 
1706  |  | xmlChar *  | 
1707  |  | xmlNodeListGetString(xmlDocPtr doc, const xmlNode *list, int inLine)  | 
1708  | 0  | { | 
1709  | 0  |     const xmlNode *node = list;  | 
1710  | 0  |     xmlChar *ret = NULL;  | 
1711  | 0  |     xmlEntityPtr ent;  | 
1712  | 0  |     int attr;  | 
1713  |  | 
  | 
1714  | 0  |     if (list == NULL)  | 
1715  | 0  |         return (NULL);  | 
1716  | 0  |     if ((list->parent != NULL) && (list->parent->type == XML_ATTRIBUTE_NODE))  | 
1717  | 0  |         attr = 1;  | 
1718  | 0  |     else  | 
1719  | 0  |         attr = 0;  | 
1720  |  | 
  | 
1721  | 0  |     while (node != NULL) { | 
1722  | 0  |         if ((node->type == XML_TEXT_NODE) ||  | 
1723  | 0  |             (node->type == XML_CDATA_SECTION_NODE)) { | 
1724  | 0  |             if (inLine) { | 
1725  | 0  |                 ret = xmlStrcat(ret, node->content);  | 
1726  | 0  |             } else { | 
1727  | 0  |                 xmlChar *buffer;  | 
1728  |  | 
  | 
1729  | 0  |     if (attr)  | 
1730  | 0  |         buffer = xmlEncodeAttributeEntities(doc, node->content);  | 
1731  | 0  |     else  | 
1732  | 0  |         buffer = xmlEncodeEntitiesReentrant(doc, node->content);  | 
1733  | 0  |                 if (buffer != NULL) { | 
1734  | 0  |                     ret = xmlStrcat(ret, buffer);  | 
1735  | 0  |                     xmlFree(buffer);  | 
1736  | 0  |                 }  | 
1737  | 0  |             }  | 
1738  | 0  |         } else if (node->type == XML_ENTITY_REF_NODE) { | 
1739  | 0  |             if (inLine) { | 
1740  | 0  |                 ent = xmlGetDocEntity(doc, node->name);  | 
1741  | 0  |                 if (ent != NULL) { | 
1742  | 0  |                     xmlChar *buffer;  | 
1743  |  |  | 
1744  |  |                     /* an entity content can be any "well balanced chunk",  | 
1745  |  |                      * i.e. the result of the content [43] production:  | 
1746  |  |                      * http://www.w3.org/TR/REC-xml#NT-content.  | 
1747  |  |                      * So it can contain text, CDATA section or nested  | 
1748  |  |                      * entity reference nodes (among others).  | 
1749  |  |                      * -> we recursive  call xmlNodeListGetString()  | 
1750  |  |                      * which handles these types */  | 
1751  | 0  |                     buffer = xmlNodeListGetString(doc, ent->children, 1);  | 
1752  | 0  |                     if (buffer != NULL) { | 
1753  | 0  |                         ret = xmlStrcat(ret, buffer);  | 
1754  | 0  |                         xmlFree(buffer);  | 
1755  | 0  |                     }  | 
1756  | 0  |                 } else { | 
1757  | 0  |                     ret = xmlStrcat(ret, node->content);  | 
1758  | 0  |                 }  | 
1759  | 0  |             } else { | 
1760  | 0  |                 xmlChar buf[2];  | 
1761  |  | 
  | 
1762  | 0  |                 buf[0] = '&';  | 
1763  | 0  |                 buf[1] = 0;  | 
1764  | 0  |                 ret = xmlStrncat(ret, buf, 1);  | 
1765  | 0  |                 ret = xmlStrcat(ret, node->name);  | 
1766  | 0  |                 buf[0] = ';';  | 
1767  | 0  |                 buf[1] = 0;  | 
1768  | 0  |                 ret = xmlStrncat(ret, buf, 1);  | 
1769  | 0  |             }  | 
1770  | 0  |         }  | 
1771  |  | #if 0  | 
1772  |  |         else { | 
1773  |  |             xmlGenericError(xmlGenericErrorContext,  | 
1774  |  |                             "xmlGetNodeListString : invalid node type %d\n",  | 
1775  |  |                             node->type);  | 
1776  |  |         }  | 
1777  |  | #endif  | 
1778  | 0  |         node = node->next;  | 
1779  | 0  |     }  | 
1780  | 0  |     return (ret);  | 
1781  | 0  | }  | 
1782  |  |  | 
1783  |  | #ifdef LIBXML_TREE_ENABLED  | 
1784  |  | /**  | 
1785  |  |  * xmlNodeListGetRawString:  | 
1786  |  |  * @doc:  the document  | 
1787  |  |  * @list:  a Node list  | 
1788  |  |  * @inLine:  should we replace entity contents or show their external form  | 
1789  |  |  *  | 
1790  |  |  * Builds the string equivalent to the text contained in the Node list  | 
1791  |  |  * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()  | 
1792  |  |  * this function doesn't do any character encoding handling.  | 
1793  |  |  *  | 
1794  |  |  * Returns a pointer to the string copy, the caller must free it with xmlFree().  | 
1795  |  |  */  | 
1796  |  | xmlChar *  | 
1797  |  | xmlNodeListGetRawString(const xmlDoc *doc, const xmlNode *list, int inLine)  | 
1798  | 0  | { | 
1799  | 0  |     const xmlNode *node = list;  | 
1800  | 0  |     xmlChar *ret = NULL;  | 
1801  | 0  |     xmlEntityPtr ent;  | 
1802  |  | 
  | 
1803  | 0  |     if (list == NULL)  | 
1804  | 0  |         return (NULL);  | 
1805  |  |  | 
1806  | 0  |     while (node != NULL) { | 
1807  | 0  |         if ((node->type == XML_TEXT_NODE) ||  | 
1808  | 0  |             (node->type == XML_CDATA_SECTION_NODE)) { | 
1809  | 0  |             if (inLine) { | 
1810  | 0  |                 ret = xmlStrcat(ret, node->content);  | 
1811  | 0  |             } else { | 
1812  | 0  |                 xmlChar *buffer;  | 
1813  |  | 
  | 
1814  | 0  |                 buffer = xmlEncodeSpecialChars(doc, node->content);  | 
1815  | 0  |                 if (buffer != NULL) { | 
1816  | 0  |                     ret = xmlStrcat(ret, buffer);  | 
1817  | 0  |                     xmlFree(buffer);  | 
1818  | 0  |                 }  | 
1819  | 0  |             }  | 
1820  | 0  |         } else if (node->type == XML_ENTITY_REF_NODE) { | 
1821  | 0  |             if (inLine) { | 
1822  | 0  |                 ent = xmlGetDocEntity(doc, node->name);  | 
1823  | 0  |                 if (ent != NULL) { | 
1824  | 0  |                     xmlChar *buffer;  | 
1825  |  |  | 
1826  |  |                     /* an entity content can be any "well balanced chunk",  | 
1827  |  |                      * i.e. the result of the content [43] production:  | 
1828  |  |                      * http://www.w3.org/TR/REC-xml#NT-content.  | 
1829  |  |                      * So it can contain text, CDATA section or nested  | 
1830  |  |                      * entity reference nodes (among others).  | 
1831  |  |                      * -> we recursive  call xmlNodeListGetRawString()  | 
1832  |  |                      * which handles these types */  | 
1833  | 0  |                     buffer =  | 
1834  | 0  |                         xmlNodeListGetRawString(doc, ent->children, 1);  | 
1835  | 0  |                     if (buffer != NULL) { | 
1836  | 0  |                         ret = xmlStrcat(ret, buffer);  | 
1837  | 0  |                         xmlFree(buffer);  | 
1838  | 0  |                     }  | 
1839  | 0  |                 } else { | 
1840  | 0  |                     ret = xmlStrcat(ret, node->content);  | 
1841  | 0  |                 }  | 
1842  | 0  |             } else { | 
1843  | 0  |                 xmlChar buf[2];  | 
1844  |  | 
  | 
1845  | 0  |                 buf[0] = '&';  | 
1846  | 0  |                 buf[1] = 0;  | 
1847  | 0  |                 ret = xmlStrncat(ret, buf, 1);  | 
1848  | 0  |                 ret = xmlStrcat(ret, node->name);  | 
1849  | 0  |                 buf[0] = ';';  | 
1850  | 0  |                 buf[1] = 0;  | 
1851  | 0  |                 ret = xmlStrncat(ret, buf, 1);  | 
1852  | 0  |             }  | 
1853  | 0  |         }  | 
1854  |  | #if 0  | 
1855  |  |         else { | 
1856  |  |             xmlGenericError(xmlGenericErrorContext,  | 
1857  |  |                             "xmlGetNodeListString : invalid node type %d\n",  | 
1858  |  |                             node->type);  | 
1859  |  |         }  | 
1860  |  | #endif  | 
1861  | 0  |         node = node->next;  | 
1862  | 0  |     }  | 
1863  | 0  |     return (ret);  | 
1864  | 0  | }  | 
1865  |  | #endif /* LIBXML_TREE_ENABLED */  | 
1866  |  |  | 
1867  |  | static xmlAttrPtr  | 
1868  |  | xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,  | 
1869  |  |                    const xmlChar * name, const xmlChar * value,  | 
1870  |  |                    int eatname)  | 
1871  | 33.3k  | { | 
1872  | 33.3k  |     xmlAttrPtr cur;  | 
1873  | 33.3k  |     xmlDocPtr doc = NULL;  | 
1874  |  |  | 
1875  | 33.3k  |     if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) { | 
1876  | 0  |         if ((eatname == 1) &&  | 
1877  | 0  |       ((node->doc == NULL) || (node->doc->dict == NULL) ||  | 
1878  | 0  |        (!(xmlDictOwns(node->doc->dict, name)))))  | 
1879  | 0  |             xmlFree((xmlChar *) name);  | 
1880  | 0  |         return (NULL);  | 
1881  | 0  |     }  | 
1882  |  |  | 
1883  |  |     /*  | 
1884  |  |      * Allocate a new property and fill the fields.  | 
1885  |  |      */  | 
1886  | 33.3k  |     cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));  | 
1887  | 33.3k  |     if (cur == NULL) { | 
1888  | 0  |         if ((eatname == 1) &&  | 
1889  | 0  |       ((node == NULL) || (node->doc == NULL) ||  | 
1890  | 0  |              (node->doc->dict == NULL) ||  | 
1891  | 0  |        (!(xmlDictOwns(node->doc->dict, name)))))  | 
1892  | 0  |             xmlFree((xmlChar *) name);  | 
1893  | 0  |         xmlTreeErrMemory("building attribute"); | 
1894  | 0  |         return (NULL);  | 
1895  | 0  |     }  | 
1896  | 33.3k  |     memset(cur, 0, sizeof(xmlAttr));  | 
1897  | 33.3k  |     cur->type = XML_ATTRIBUTE_NODE;  | 
1898  |  |  | 
1899  | 33.3k  |     cur->parent = node;  | 
1900  | 33.3k  |     if (node != NULL) { | 
1901  | 33.3k  |         doc = node->doc;  | 
1902  | 33.3k  |         cur->doc = doc;  | 
1903  | 33.3k  |     }  | 
1904  | 33.3k  |     cur->ns = ns;  | 
1905  |  |  | 
1906  | 33.3k  |     if (eatname == 0) { | 
1907  | 0  |         if ((doc != NULL) && (doc->dict != NULL))  | 
1908  | 0  |             cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);  | 
1909  | 0  |         else  | 
1910  | 0  |             cur->name = xmlStrdup(name);  | 
1911  | 0  |     } else  | 
1912  | 33.3k  |         cur->name = name;  | 
1913  |  |  | 
1914  | 33.3k  |     if (value != NULL) { | 
1915  | 0  |         xmlNodePtr tmp;  | 
1916  |  | 
  | 
1917  | 0  |         cur->children = xmlNewDocText(doc, value);  | 
1918  | 0  |         cur->last = NULL;  | 
1919  | 0  |         tmp = cur->children;  | 
1920  | 0  |         while (tmp != NULL) { | 
1921  | 0  |             tmp->parent = (xmlNodePtr) cur;  | 
1922  | 0  |             if (tmp->next == NULL)  | 
1923  | 0  |                 cur->last = tmp;  | 
1924  | 0  |             tmp = tmp->next;  | 
1925  | 0  |         }  | 
1926  | 0  |     }  | 
1927  |  |  | 
1928  |  |     /*  | 
1929  |  |      * Add it at the end to preserve parsing order ...  | 
1930  |  |      */  | 
1931  | 33.3k  |     if (node != NULL) { | 
1932  | 33.3k  |         if (node->properties == NULL) { | 
1933  | 29.6k  |             node->properties = cur;  | 
1934  | 29.6k  |         } else { | 
1935  | 3.70k  |             xmlAttrPtr prev = node->properties;  | 
1936  |  |  | 
1937  | 3.70k  |             while (prev->next != NULL)  | 
1938  | 0  |                 prev = prev->next;  | 
1939  | 3.70k  |             prev->next = cur;  | 
1940  | 3.70k  |             cur->prev = prev;  | 
1941  | 3.70k  |         }  | 
1942  | 33.3k  |     }  | 
1943  |  |  | 
1944  | 33.3k  |     if ((value != NULL) && (node != NULL) &&  | 
1945  | 33.3k  |         (xmlIsID(node->doc, node, cur) == 1))  | 
1946  | 0  |         xmlAddID(NULL, node->doc, value, cur);  | 
1947  |  |  | 
1948  | 33.3k  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
1949  | 0  |         xmlRegisterNodeDefaultValue((xmlNodePtr) cur);  | 
1950  | 33.3k  |     return (cur);  | 
1951  | 33.3k  | }  | 
1952  |  |  | 
1953  |  | #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \  | 
1954  |  |     defined(LIBXML_SCHEMAS_ENABLED)  | 
1955  |  | /**  | 
1956  |  |  * xmlNewProp:  | 
1957  |  |  * @node:  the holding node  | 
1958  |  |  * @name:  the name of the attribute  | 
1959  |  |  * @value:  the value of the attribute  | 
1960  |  |  *  | 
1961  |  |  * Create a new property carried by a node.  | 
1962  |  |  * Returns a pointer to the attribute  | 
1963  |  |  */  | 
1964  |  | xmlAttrPtr  | 
1965  | 0  | xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { | 
1966  |  | 
  | 
1967  | 0  |     if (name == NULL) { | 
1968  |  | #ifdef DEBUG_TREE  | 
1969  |  |         xmlGenericError(xmlGenericErrorContext,  | 
1970  |  |     "xmlNewProp : name == NULL\n");  | 
1971  |  | #endif  | 
1972  | 0  |   return(NULL);  | 
1973  | 0  |     }  | 
1974  |  |  | 
1975  | 0  |   return xmlNewPropInternal(node, NULL, name, value, 0);  | 
1976  | 0  | }  | 
1977  |  | #endif /* LIBXML_TREE_ENABLED */  | 
1978  |  |  | 
1979  |  | /**  | 
1980  |  |  * xmlNewNsProp:  | 
1981  |  |  * @node:  the holding node  | 
1982  |  |  * @ns:  the namespace  | 
1983  |  |  * @name:  the name of the attribute  | 
1984  |  |  * @value:  the value of the attribute  | 
1985  |  |  *  | 
1986  |  |  * Create a new property tagged with a namespace and carried by a node.  | 
1987  |  |  * Returns a pointer to the attribute  | 
1988  |  |  */  | 
1989  |  | xmlAttrPtr  | 
1990  |  | xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,  | 
1991  | 0  |            const xmlChar *value) { | 
1992  |  | 
  | 
1993  | 0  |     if (name == NULL) { | 
1994  |  | #ifdef DEBUG_TREE  | 
1995  |  |         xmlGenericError(xmlGenericErrorContext,  | 
1996  |  |     "xmlNewNsProp : name == NULL\n");  | 
1997  |  | #endif  | 
1998  | 0  |   return(NULL);  | 
1999  | 0  |     }  | 
2000  |  |  | 
2001  | 0  |     return xmlNewPropInternal(node, ns, name, value, 0);  | 
2002  | 0  | }  | 
2003  |  |  | 
2004  |  | /**  | 
2005  |  |  * xmlNewNsPropEatName:  | 
2006  |  |  * @node:  the holding node  | 
2007  |  |  * @ns:  the namespace  | 
2008  |  |  * @name:  the name of the attribute  | 
2009  |  |  * @value:  the value of the attribute  | 
2010  |  |  *  | 
2011  |  |  * Create a new property tagged with a namespace and carried by a node.  | 
2012  |  |  * Returns a pointer to the attribute  | 
2013  |  |  */  | 
2014  |  | xmlAttrPtr  | 
2015  |  | xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name,  | 
2016  | 33.3k  |            const xmlChar *value) { | 
2017  |  |  | 
2018  | 33.3k  |     if (name == NULL) { | 
2019  |  | #ifdef DEBUG_TREE  | 
2020  |  |         xmlGenericError(xmlGenericErrorContext,  | 
2021  |  |     "xmlNewNsPropEatName : name == NULL\n");  | 
2022  |  | #endif  | 
2023  | 0  |   return(NULL);  | 
2024  | 0  |     }  | 
2025  |  |  | 
2026  | 33.3k  |     return xmlNewPropInternal(node, ns, name, value, 1);  | 
2027  | 33.3k  | }  | 
2028  |  |  | 
2029  |  | /**  | 
2030  |  |  * xmlNewDocProp:  | 
2031  |  |  * @doc:  the document  | 
2032  |  |  * @name:  the name of the attribute  | 
2033  |  |  * @value:  the value of the attribute  | 
2034  |  |  *  | 
2035  |  |  * Create a new property carried by a document.  | 
2036  |  |  * NOTE: @value is supposed to be a piece of XML CDATA, so it allows entity  | 
2037  |  |  *       references, but XML special chars need to be escaped first by using  | 
2038  |  |  *       xmlEncodeEntitiesReentrant(). Use xmlNewProp() if you don't need  | 
2039  |  |  *       entities support.  | 
2040  |  |  *  | 
2041  |  |  * Returns a pointer to the attribute  | 
2042  |  |  */  | 
2043  |  | xmlAttrPtr  | 
2044  | 0  | xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) { | 
2045  | 0  |     xmlAttrPtr cur;  | 
2046  |  | 
  | 
2047  | 0  |     if (name == NULL) { | 
2048  |  | #ifdef DEBUG_TREE  | 
2049  |  |         xmlGenericError(xmlGenericErrorContext,  | 
2050  |  |     "xmlNewDocProp : name == NULL\n");  | 
2051  |  | #endif  | 
2052  | 0  |   return(NULL);  | 
2053  | 0  |     }  | 
2054  |  |  | 
2055  |  |     /*  | 
2056  |  |      * Allocate a new property and fill the fields.  | 
2057  |  |      */  | 
2058  | 0  |     cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));  | 
2059  | 0  |     if (cur == NULL) { | 
2060  | 0  |   xmlTreeErrMemory("building attribute"); | 
2061  | 0  |   return(NULL);  | 
2062  | 0  |     }  | 
2063  | 0  |     memset(cur, 0, sizeof(xmlAttr));  | 
2064  | 0  |     cur->type = XML_ATTRIBUTE_NODE;  | 
2065  |  | 
  | 
2066  | 0  |     if ((doc != NULL) && (doc->dict != NULL))  | 
2067  | 0  |   cur->name = xmlDictLookup(doc->dict, name, -1);  | 
2068  | 0  |     else  | 
2069  | 0  |   cur->name = xmlStrdup(name);  | 
2070  | 0  |     cur->doc = doc;  | 
2071  | 0  |     if (value != NULL) { | 
2072  | 0  |   xmlNodePtr tmp;  | 
2073  |  | 
  | 
2074  | 0  |   cur->children = xmlStringGetNodeList(doc, value);  | 
2075  | 0  |   cur->last = NULL;  | 
2076  |  | 
  | 
2077  | 0  |   tmp = cur->children;  | 
2078  | 0  |   while (tmp != NULL) { | 
2079  | 0  |       tmp->parent = (xmlNodePtr) cur;  | 
2080  | 0  |       if (tmp->next == NULL)  | 
2081  | 0  |     cur->last = tmp;  | 
2082  | 0  |       tmp = tmp->next;  | 
2083  | 0  |   }  | 
2084  | 0  |     }  | 
2085  |  | 
  | 
2086  | 0  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
2087  | 0  |   xmlRegisterNodeDefaultValue((xmlNodePtr)cur);  | 
2088  | 0  |     return(cur);  | 
2089  | 0  | }  | 
2090  |  |  | 
2091  |  | /**  | 
2092  |  |  * xmlFreePropList:  | 
2093  |  |  * @cur:  the first property in the list  | 
2094  |  |  *  | 
2095  |  |  * Free a property and all its siblings, all the children are freed too.  | 
2096  |  |  */  | 
2097  |  | void  | 
2098  | 0  | xmlFreePropList(xmlAttrPtr cur) { | 
2099  | 0  |     xmlAttrPtr next;  | 
2100  | 0  |     if (cur == NULL) return;  | 
2101  | 0  |     while (cur != NULL) { | 
2102  | 0  |         next = cur->next;  | 
2103  | 0  |         xmlFreeProp(cur);  | 
2104  | 0  |   cur = next;  | 
2105  | 0  |     }  | 
2106  | 0  | }  | 
2107  |  |  | 
2108  |  | /**  | 
2109  |  |  * xmlFreeProp:  | 
2110  |  |  * @cur:  an attribute  | 
2111  |  |  *  | 
2112  |  |  * Free one attribute, all the content is freed too  | 
2113  |  |  */  | 
2114  |  | void  | 
2115  | 0  | xmlFreeProp(xmlAttrPtr cur) { | 
2116  | 0  |     xmlDictPtr dict = NULL;  | 
2117  | 0  |     if (cur == NULL) return;  | 
2118  |  |  | 
2119  | 0  |     if (cur->doc != NULL) dict = cur->doc->dict;  | 
2120  |  | 
  | 
2121  | 0  |     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))  | 
2122  | 0  |   xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);  | 
2123  |  |  | 
2124  |  |     /* Check for ID removal -> leading to invalid references ! */  | 
2125  | 0  |     if ((cur->doc != NULL) && (cur->atype == XML_ATTRIBUTE_ID)) { | 
2126  | 0  |       xmlRemoveID(cur->doc, cur);  | 
2127  | 0  |     }  | 
2128  | 0  |     if (cur->children != NULL) xmlFreeNodeList(cur->children);  | 
2129  | 0  |     DICT_FREE(cur->name)  | 
2130  | 0  |     xmlFree(cur);  | 
2131  | 0  | }  | 
2132  |  |  | 
2133  |  | /**  | 
2134  |  |  * xmlRemoveProp:  | 
2135  |  |  * @cur:  an attribute  | 
2136  |  |  *  | 
2137  |  |  * Unlink and free one attribute, all the content is freed too  | 
2138  |  |  * Note this doesn't work for namespace definition attributes  | 
2139  |  |  *  | 
2140  |  |  * Returns 0 if success and -1 in case of error.  | 
2141  |  |  */  | 
2142  |  | int  | 
2143  | 0  | xmlRemoveProp(xmlAttrPtr cur) { | 
2144  | 0  |     xmlAttrPtr tmp;  | 
2145  | 0  |     if (cur == NULL) { | 
2146  |  | #ifdef DEBUG_TREE  | 
2147  |  |         xmlGenericError(xmlGenericErrorContext,  | 
2148  |  |     "xmlRemoveProp : cur == NULL\n");  | 
2149  |  | #endif  | 
2150  | 0  |   return(-1);  | 
2151  | 0  |     }  | 
2152  | 0  |     if (cur->parent == NULL) { | 
2153  |  | #ifdef DEBUG_TREE  | 
2154  |  |         xmlGenericError(xmlGenericErrorContext,  | 
2155  |  |     "xmlRemoveProp : cur->parent == NULL\n");  | 
2156  |  | #endif  | 
2157  | 0  |   return(-1);  | 
2158  | 0  |     }  | 
2159  | 0  |     tmp = cur->parent->properties;  | 
2160  | 0  |     if (tmp == cur) { | 
2161  | 0  |         cur->parent->properties = cur->next;  | 
2162  | 0  |     if (cur->next != NULL)  | 
2163  | 0  |       cur->next->prev = NULL;  | 
2164  | 0  |   xmlFreeProp(cur);  | 
2165  | 0  |   return(0);  | 
2166  | 0  |     }  | 
2167  | 0  |     while (tmp != NULL) { | 
2168  | 0  |   if (tmp->next == cur) { | 
2169  | 0  |       tmp->next = cur->next;  | 
2170  | 0  |       if (tmp->next != NULL)  | 
2171  | 0  |     tmp->next->prev = tmp;  | 
2172  | 0  |       xmlFreeProp(cur);  | 
2173  | 0  |       return(0);  | 
2174  | 0  |   }  | 
2175  | 0  |         tmp = tmp->next;  | 
2176  | 0  |     }  | 
2177  |  | #ifdef DEBUG_TREE  | 
2178  |  |     xmlGenericError(xmlGenericErrorContext,  | 
2179  |  |       "xmlRemoveProp : attribute not owned by its node\n");  | 
2180  |  | #endif  | 
2181  | 0  |     return(-1);  | 
2182  | 0  | }  | 
2183  |  |  | 
2184  |  | /**  | 
2185  |  |  * xmlNewDocPI:  | 
2186  |  |  * @doc:  the target document  | 
2187  |  |  * @name:  the processing instruction name  | 
2188  |  |  * @content:  the PI content  | 
2189  |  |  *  | 
2190  |  |  * Creation of a processing instruction element.  | 
2191  |  |  * Returns a pointer to the new node object.  | 
2192  |  |  */  | 
2193  |  | xmlNodePtr  | 
2194  | 7.40k  | xmlNewDocPI(xmlDocPtr doc, const xmlChar *name, const xmlChar *content) { | 
2195  | 7.40k  |     xmlNodePtr cur;  | 
2196  |  |  | 
2197  | 7.40k  |     if (name == NULL) { | 
2198  |  | #ifdef DEBUG_TREE  | 
2199  |  |         xmlGenericError(xmlGenericErrorContext,  | 
2200  |  |     "xmlNewPI : name == NULL\n");  | 
2201  |  | #endif  | 
2202  | 0  |   return(NULL);  | 
2203  | 0  |     }  | 
2204  |  |  | 
2205  |  |     /*  | 
2206  |  |      * Allocate a new node and fill the fields.  | 
2207  |  |      */  | 
2208  | 7.40k  |     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));  | 
2209  | 7.40k  |     if (cur == NULL) { | 
2210  | 0  |   xmlTreeErrMemory("building PI"); | 
2211  | 0  |   return(NULL);  | 
2212  | 0  |     }  | 
2213  | 7.40k  |     memset(cur, 0, sizeof(xmlNode));  | 
2214  | 7.40k  |     cur->type = XML_PI_NODE;  | 
2215  |  |  | 
2216  | 7.40k  |     if ((doc != NULL) && (doc->dict != NULL))  | 
2217  | 7.40k  |         cur->name = xmlDictLookup(doc->dict, name, -1);  | 
2218  | 0  |     else  | 
2219  | 0  |   cur->name = xmlStrdup(name);  | 
2220  | 7.40k  |     if (content != NULL) { | 
2221  | 7.40k  |   cur->content = xmlStrdup(content);  | 
2222  | 7.40k  |     }  | 
2223  | 7.40k  |     cur->doc = doc;  | 
2224  |  |  | 
2225  | 7.40k  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
2226  | 0  |   xmlRegisterNodeDefaultValue((xmlNodePtr)cur);  | 
2227  | 7.40k  |     return(cur);  | 
2228  | 7.40k  | }  | 
2229  |  |  | 
2230  |  | /**  | 
2231  |  |  * xmlNewPI:  | 
2232  |  |  * @name:  the processing instruction name  | 
2233  |  |  * @content:  the PI content  | 
2234  |  |  *  | 
2235  |  |  * Creation of a processing instruction element.  | 
2236  |  |  *  | 
2237  |  |  * Use of this function is DISCOURAGED in favor of xmlNewDocPI.  | 
2238  |  |  *  | 
2239  |  |  * Returns a pointer to the new node object.  | 
2240  |  |  */  | 
2241  |  | xmlNodePtr  | 
2242  | 0  | xmlNewPI(const xmlChar *name, const xmlChar *content) { | 
2243  | 0  |     return(xmlNewDocPI(NULL, name, content));  | 
2244  | 0  | }  | 
2245  |  |  | 
2246  |  | /**  | 
2247  |  |  * xmlNewNode:  | 
2248  |  |  * @ns:  namespace if any  | 
2249  |  |  * @name:  the node name  | 
2250  |  |  *  | 
2251  |  |  * Creation of a new node element. @ns is optional (NULL).  | 
2252  |  |  *  | 
2253  |  |  * Use of this function is DISCOURAGED in favor of xmlNewDocNode.  | 
2254  |  |  *  | 
2255  |  |  * Returns a pointer to the new node object. Uses xmlStrdup() to make  | 
2256  |  |  * copy of @name.  | 
2257  |  |  */  | 
2258  |  | xmlNodePtr  | 
2259  | 0  | xmlNewNode(xmlNsPtr ns, const xmlChar *name) { | 
2260  | 0  |     xmlNodePtr cur;  | 
2261  |  | 
  | 
2262  | 0  |     if (name == NULL) { | 
2263  |  | #ifdef DEBUG_TREE  | 
2264  |  |         xmlGenericError(xmlGenericErrorContext,  | 
2265  |  |     "xmlNewNode : name == NULL\n");  | 
2266  |  | #endif  | 
2267  | 0  |   return(NULL);  | 
2268  | 0  |     }  | 
2269  |  |  | 
2270  |  |     /*  | 
2271  |  |      * Allocate a new node and fill the fields.  | 
2272  |  |      */  | 
2273  | 0  |     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));  | 
2274  | 0  |     if (cur == NULL) { | 
2275  | 0  |   xmlTreeErrMemory("building node"); | 
2276  | 0  |   return(NULL);  | 
2277  | 0  |     }  | 
2278  | 0  |     memset(cur, 0, sizeof(xmlNode));  | 
2279  | 0  |     cur->type = XML_ELEMENT_NODE;  | 
2280  |  | 
  | 
2281  | 0  |     cur->name = xmlStrdup(name);  | 
2282  | 0  |     cur->ns = ns;  | 
2283  |  | 
  | 
2284  | 0  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
2285  | 0  |   xmlRegisterNodeDefaultValue(cur);  | 
2286  | 0  |     return(cur);  | 
2287  | 0  | }  | 
2288  |  |  | 
2289  |  | /**  | 
2290  |  |  * xmlNewNodeEatName:  | 
2291  |  |  * @ns:  namespace if any  | 
2292  |  |  * @name:  the node name  | 
2293  |  |  *  | 
2294  |  |  * Creation of a new node element. @ns is optional (NULL).  | 
2295  |  |  *  | 
2296  |  |  * Use of this function is DISCOURAGED in favor of xmlNewDocNodeEatName.  | 
2297  |  |  *  | 
2298  |  |  * Returns a pointer to the new node object, with pointer @name as  | 
2299  |  |  * new node's name. Use xmlNewNode() if a copy of @name string is  | 
2300  |  |  * is needed as new node's name.  | 
2301  |  |  */  | 
2302  |  | xmlNodePtr  | 
2303  | 3.74M  | xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) { | 
2304  | 3.74M  |     xmlNodePtr cur;  | 
2305  |  |  | 
2306  | 3.74M  |     if (name == NULL) { | 
2307  |  | #ifdef DEBUG_TREE  | 
2308  |  |         xmlGenericError(xmlGenericErrorContext,  | 
2309  |  |     "xmlNewNode : name == NULL\n");  | 
2310  |  | #endif  | 
2311  | 0  |   return(NULL);  | 
2312  | 0  |     }  | 
2313  |  |  | 
2314  |  |     /*  | 
2315  |  |      * Allocate a new node and fill the fields.  | 
2316  |  |      */  | 
2317  | 3.74M  |     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));  | 
2318  | 3.74M  |     if (cur == NULL) { | 
2319  | 0  |   xmlTreeErrMemory("building node"); | 
2320  |  |   /* we can't check here that name comes from the doc dictionary */  | 
2321  | 0  |   return(NULL);  | 
2322  | 0  |     }  | 
2323  | 3.74M  |     memset(cur, 0, sizeof(xmlNode));  | 
2324  | 3.74M  |     cur->type = XML_ELEMENT_NODE;  | 
2325  |  |  | 
2326  | 3.74M  |     cur->name = name;  | 
2327  | 3.74M  |     cur->ns = ns;  | 
2328  |  |  | 
2329  | 3.74M  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
2330  | 0  |   xmlRegisterNodeDefaultValue((xmlNodePtr)cur);  | 
2331  | 3.74M  |     return(cur);  | 
2332  | 3.74M  | }  | 
2333  |  |  | 
2334  |  | /**  | 
2335  |  |  * xmlNewDocNode:  | 
2336  |  |  * @doc:  the document  | 
2337  |  |  * @ns:  namespace if any  | 
2338  |  |  * @name:  the node name  | 
2339  |  |  * @content:  the XML text content if any  | 
2340  |  |  *  | 
2341  |  |  * Creation of a new node element within a document. @ns and @content  | 
2342  |  |  * are optional (NULL).  | 
2343  |  |  * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities  | 
2344  |  |  *       references, but XML special chars need to be escaped first by using  | 
2345  |  |  *       xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't  | 
2346  |  |  *       need entities support.  | 
2347  |  |  *  | 
2348  |  |  * Returns a pointer to the new node object.  | 
2349  |  |  */  | 
2350  |  | xmlNodePtr  | 
2351  |  | xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,  | 
2352  | 3.70M  |               const xmlChar *name, const xmlChar *content) { | 
2353  | 3.70M  |     xmlNodePtr cur;  | 
2354  |  |  | 
2355  | 3.70M  |     if ((doc != NULL) && (doc->dict != NULL))  | 
2356  | 3.70M  |         cur = xmlNewNodeEatName(ns, (xmlChar *)  | 
2357  | 3.70M  |                           xmlDictLookup(doc->dict, name, -1));  | 
2358  | 0  |     else  | 
2359  | 0  |   cur = xmlNewNode(ns, name);  | 
2360  | 3.70M  |     if (cur != NULL) { | 
2361  | 3.70M  |         cur->doc = doc;  | 
2362  | 3.70M  |   if (content != NULL) { | 
2363  | 0  |       cur->children = xmlStringGetNodeList(doc, content);  | 
2364  | 0  |       UPDATE_LAST_CHILD_AND_PARENT(cur)  | 
2365  | 0  |   }  | 
2366  | 3.70M  |     }  | 
2367  |  |  | 
2368  | 3.70M  |     return(cur);  | 
2369  | 3.70M  | }  | 
2370  |  |  | 
2371  |  | /**  | 
2372  |  |  * xmlNewDocNodeEatName:  | 
2373  |  |  * @doc:  the document  | 
2374  |  |  * @ns:  namespace if any  | 
2375  |  |  * @name:  the node name  | 
2376  |  |  * @content:  the XML text content if any  | 
2377  |  |  *  | 
2378  |  |  * Creation of a new node element within a document. @ns and @content  | 
2379  |  |  * are optional (NULL).  | 
2380  |  |  * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities  | 
2381  |  |  *       references, but XML special chars need to be escaped first by using  | 
2382  |  |  *       xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't  | 
2383  |  |  *       need entities support.  | 
2384  |  |  *  | 
2385  |  |  * Returns a pointer to the new node object.  | 
2386  |  |  */  | 
2387  |  | xmlNodePtr  | 
2388  |  | xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns,  | 
2389  | 44.4k  |               xmlChar *name, const xmlChar *content) { | 
2390  | 44.4k  |     xmlNodePtr cur;  | 
2391  |  |  | 
2392  | 44.4k  |     cur = xmlNewNodeEatName(ns, name);  | 
2393  | 44.4k  |     if (cur != NULL) { | 
2394  | 44.4k  |         cur->doc = doc;  | 
2395  | 44.4k  |   if (content != NULL) { | 
2396  | 0  |       cur->children = xmlStringGetNodeList(doc, content);  | 
2397  | 0  |       UPDATE_LAST_CHILD_AND_PARENT(cur)  | 
2398  | 0  |   }  | 
2399  | 44.4k  |     } else { | 
2400  |  |         /* if name don't come from the doc dictionary free it here */  | 
2401  | 0  |         if ((name != NULL) &&  | 
2402  | 0  |             ((doc == NULL) || (doc->dict == NULL) ||  | 
2403  | 0  |        (!(xmlDictOwns(doc->dict, name)))))  | 
2404  | 0  |       xmlFree(name);  | 
2405  | 0  |     }  | 
2406  | 44.4k  |     return(cur);  | 
2407  | 44.4k  | }  | 
2408  |  |  | 
2409  |  | #ifdef LIBXML_TREE_ENABLED  | 
2410  |  | /**  | 
2411  |  |  * xmlNewDocRawNode:  | 
2412  |  |  * @doc:  the document  | 
2413  |  |  * @ns:  namespace if any  | 
2414  |  |  * @name:  the node name  | 
2415  |  |  * @content:  the text content if any  | 
2416  |  |  *  | 
2417  |  |  * Creation of a new node element within a document. @ns and @content  | 
2418  |  |  * are optional (NULL).  | 
2419  |  |  *  | 
2420  |  |  * Returns a pointer to the new node object.  | 
2421  |  |  */  | 
2422  |  | xmlNodePtr  | 
2423  |  | xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,  | 
2424  | 3.70M  |                  const xmlChar *name, const xmlChar *content) { | 
2425  | 3.70M  |     xmlNodePtr cur;  | 
2426  |  |  | 
2427  | 3.70M  |     cur = xmlNewDocNode(doc, ns, name, NULL);  | 
2428  | 3.70M  |     if (cur != NULL) { | 
2429  | 3.70M  |         cur->doc = doc;  | 
2430  | 3.70M  |   if (content != NULL) { | 
2431  | 3.70M  |       cur->children = xmlNewDocText(doc, content);  | 
2432  | 3.70M  |       UPDATE_LAST_CHILD_AND_PARENT(cur)  | 
2433  | 3.70M  |   }  | 
2434  | 3.70M  |     }  | 
2435  | 3.70M  |     return(cur);  | 
2436  | 3.70M  | }  | 
2437  |  |  | 
2438  |  | /**  | 
2439  |  |  * xmlNewDocFragment:  | 
2440  |  |  * @doc:  the document owning the fragment  | 
2441  |  |  *  | 
2442  |  |  * Creation of a new Fragment node.  | 
2443  |  |  * Returns a pointer to the new node object.  | 
2444  |  |  */  | 
2445  |  | xmlNodePtr  | 
2446  | 0  | xmlNewDocFragment(xmlDocPtr doc) { | 
2447  | 0  |     xmlNodePtr cur;  | 
2448  |  |  | 
2449  |  |     /*  | 
2450  |  |      * Allocate a new DocumentFragment node and fill the fields.  | 
2451  |  |      */  | 
2452  | 0  |     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));  | 
2453  | 0  |     if (cur == NULL) { | 
2454  | 0  |   xmlTreeErrMemory("building fragment"); | 
2455  | 0  |   return(NULL);  | 
2456  | 0  |     }  | 
2457  | 0  |     memset(cur, 0, sizeof(xmlNode));  | 
2458  | 0  |     cur->type = XML_DOCUMENT_FRAG_NODE;  | 
2459  |  | 
  | 
2460  | 0  |     cur->doc = doc;  | 
2461  |  | 
  | 
2462  | 0  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
2463  | 0  |   xmlRegisterNodeDefaultValue(cur);  | 
2464  | 0  |     return(cur);  | 
2465  | 0  | }  | 
2466  |  | #endif /* LIBXML_TREE_ENABLED */  | 
2467  |  |  | 
2468  |  | /**  | 
2469  |  |  * xmlNewText:  | 
2470  |  |  * @content:  the text content  | 
2471  |  |  *  | 
2472  |  |  * Creation of a new text node.  | 
2473  |  |  *  | 
2474  |  |  * Use of this function is DISCOURAGED in favor of xmlNewDocText.  | 
2475  |  |  *  | 
2476  |  |  * Returns a pointer to the new node object.  | 
2477  |  |  */  | 
2478  |  | xmlNodePtr  | 
2479  | 3.70M  | xmlNewText(const xmlChar *content) { | 
2480  | 3.70M  |     xmlNodePtr cur;  | 
2481  |  |  | 
2482  |  |     /*  | 
2483  |  |      * Allocate a new node and fill the fields.  | 
2484  |  |      */  | 
2485  | 3.70M  |     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));  | 
2486  | 3.70M  |     if (cur == NULL) { | 
2487  | 0  |   xmlTreeErrMemory("building text"); | 
2488  | 0  |   return(NULL);  | 
2489  | 0  |     }  | 
2490  | 3.70M  |     memset(cur, 0, sizeof(xmlNode));  | 
2491  | 3.70M  |     cur->type = XML_TEXT_NODE;  | 
2492  |  |  | 
2493  | 3.70M  |     cur->name = xmlStringText;  | 
2494  | 3.70M  |     if (content != NULL) { | 
2495  | 3.70M  |   cur->content = xmlStrdup(content);  | 
2496  | 3.70M  |     }  | 
2497  |  |  | 
2498  | 3.70M  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
2499  | 0  |   xmlRegisterNodeDefaultValue(cur);  | 
2500  | 3.70M  |     return(cur);  | 
2501  | 3.70M  | }  | 
2502  |  |  | 
2503  |  | #ifdef LIBXML_TREE_ENABLED  | 
2504  |  | /**  | 
2505  |  |  * xmlNewTextChild:  | 
2506  |  |  * @parent:  the parent node  | 
2507  |  |  * @ns:  a namespace if any  | 
2508  |  |  * @name:  the name of the child  | 
2509  |  |  * @content:  the text content of the child if any.  | 
2510  |  |  *  | 
2511  |  |  * Creation of a new child element, added at the end of @parent children list.  | 
2512  |  |  * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly  | 
2513  |  |  * created element inherits the namespace of @parent. If @content is non NULL,  | 
2514  |  |  * a child TEXT node will be created containing the string @content.  | 
2515  |  |  * NOTE: Use xmlNewChild() if @content will contain entities that need to be  | 
2516  |  |  * preserved. Use this function, xmlNewTextChild(), if you need to ensure that  | 
2517  |  |  * reserved XML chars that might appear in @content, such as the ampersand,  | 
2518  |  |  * greater-than or less-than signs, are automatically replaced by their XML  | 
2519  |  |  * escaped entity representations.  | 
2520  |  |  *  | 
2521  |  |  * Returns a pointer to the new node object.  | 
2522  |  |  */  | 
2523  |  | xmlNodePtr  | 
2524  |  | xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,  | 
2525  | 413k  |             const xmlChar *name, const xmlChar *content) { | 
2526  | 413k  |     xmlNodePtr cur, prev;  | 
2527  |  |  | 
2528  | 413k  |     if (parent == NULL) { | 
2529  |  | #ifdef DEBUG_TREE  | 
2530  |  |         xmlGenericError(xmlGenericErrorContext,  | 
2531  |  |     "xmlNewTextChild : parent == NULL\n");  | 
2532  |  | #endif  | 
2533  | 0  |   return(NULL);  | 
2534  | 0  |     }  | 
2535  |  |  | 
2536  | 413k  |     if (name == NULL) { | 
2537  |  | #ifdef DEBUG_TREE  | 
2538  |  |         xmlGenericError(xmlGenericErrorContext,  | 
2539  |  |     "xmlNewTextChild : name == NULL\n");  | 
2540  |  | #endif  | 
2541  | 0  |   return(NULL);  | 
2542  | 0  |     }  | 
2543  |  |  | 
2544  |  |     /*  | 
2545  |  |      * Allocate a new node  | 
2546  |  |      */  | 
2547  | 413k  |     if (parent->type == XML_ELEMENT_NODE) { | 
2548  | 0  |   if (ns == NULL)  | 
2549  | 0  |       cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);  | 
2550  | 0  |   else  | 
2551  | 0  |       cur = xmlNewDocRawNode(parent->doc, ns, name, content);  | 
2552  | 413k  |     } else if ((parent->type == XML_DOCUMENT_NODE) ||  | 
2553  | 413k  |          (parent->type == XML_HTML_DOCUMENT_NODE)) { | 
2554  | 413k  |   if (ns == NULL)  | 
2555  | 413k  |       cur = xmlNewDocRawNode((xmlDocPtr) parent, NULL, name, content);  | 
2556  | 0  |   else  | 
2557  | 0  |       cur = xmlNewDocRawNode((xmlDocPtr) parent, ns, name, content);  | 
2558  | 413k  |     } else if (parent->type == XML_DOCUMENT_FRAG_NODE) { | 
2559  | 0  |       cur = xmlNewDocRawNode( parent->doc, ns, name, content);  | 
2560  | 0  |     } else { | 
2561  | 0  |   return(NULL);  | 
2562  | 0  |     }  | 
2563  | 413k  |     if (cur == NULL) return(NULL);  | 
2564  |  |  | 
2565  |  |     /*  | 
2566  |  |      * add the new element at the end of the children list.  | 
2567  |  |      */  | 
2568  | 413k  |     cur->type = XML_ELEMENT_NODE;  | 
2569  | 413k  |     cur->parent = parent;  | 
2570  | 413k  |     cur->doc = parent->doc;  | 
2571  | 413k  |     if (parent->children == NULL) { | 
2572  | 49.0k  |         parent->children = cur;  | 
2573  | 49.0k  |   parent->last = cur;  | 
2574  | 363k  |     } else { | 
2575  | 363k  |         prev = parent->last;  | 
2576  | 363k  |   prev->next = cur;  | 
2577  | 363k  |   cur->prev = prev;  | 
2578  | 363k  |   parent->last = cur;  | 
2579  | 363k  |     }  | 
2580  |  |  | 
2581  | 413k  |     return(cur);  | 
2582  | 413k  | }  | 
2583  |  | #endif /* LIBXML_TREE_ENABLED */  | 
2584  |  |  | 
2585  |  | /**  | 
2586  |  |  * xmlNewCharRef:  | 
2587  |  |  * @doc: the document  | 
2588  |  |  * @name:  the char ref string, starting with # or "&# ... ;"  | 
2589  |  |  *  | 
2590  |  |  * Creation of a new character reference node.  | 
2591  |  |  * Returns a pointer to the new node object.  | 
2592  |  |  */  | 
2593  |  | xmlNodePtr  | 
2594  | 0  | xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) { | 
2595  | 0  |     xmlNodePtr cur;  | 
2596  |  | 
  | 
2597  | 0  |     if (name == NULL)  | 
2598  | 0  |         return(NULL);  | 
2599  |  |  | 
2600  |  |     /*  | 
2601  |  |      * Allocate a new node and fill the fields.  | 
2602  |  |      */  | 
2603  | 0  |     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));  | 
2604  | 0  |     if (cur == NULL) { | 
2605  | 0  |   xmlTreeErrMemory("building character reference"); | 
2606  | 0  |   return(NULL);  | 
2607  | 0  |     }  | 
2608  | 0  |     memset(cur, 0, sizeof(xmlNode));  | 
2609  | 0  |     cur->type = XML_ENTITY_REF_NODE;  | 
2610  |  | 
  | 
2611  | 0  |     cur->doc = doc;  | 
2612  | 0  |     if (name[0] == '&') { | 
2613  | 0  |         int len;  | 
2614  | 0  |         name++;  | 
2615  | 0  |   len = xmlStrlen(name);  | 
2616  | 0  |   if (name[len - 1] == ';')  | 
2617  | 0  |       cur->name = xmlStrndup(name, len - 1);  | 
2618  | 0  |   else  | 
2619  | 0  |       cur->name = xmlStrndup(name, len);  | 
2620  | 0  |     } else  | 
2621  | 0  |   cur->name = xmlStrdup(name);  | 
2622  |  | 
  | 
2623  | 0  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
2624  | 0  |   xmlRegisterNodeDefaultValue(cur);  | 
2625  | 0  |     return(cur);  | 
2626  | 0  | }  | 
2627  |  |  | 
2628  |  | /**  | 
2629  |  |  * xmlNewReference:  | 
2630  |  |  * @doc: the document  | 
2631  |  |  * @name:  the reference name, or the reference string with & and ;  | 
2632  |  |  *  | 
2633  |  |  * Creation of a new reference node.  | 
2634  |  |  * Returns a pointer to the new node object.  | 
2635  |  |  */  | 
2636  |  | xmlNodePtr  | 
2637  | 0  | xmlNewReference(const xmlDoc *doc, const xmlChar *name) { | 
2638  | 0  |     xmlNodePtr cur;  | 
2639  | 0  |     xmlEntityPtr ent;  | 
2640  |  | 
  | 
2641  | 0  |     if (name == NULL)  | 
2642  | 0  |         return(NULL);  | 
2643  |  |  | 
2644  |  |     /*  | 
2645  |  |      * Allocate a new node and fill the fields.  | 
2646  |  |      */  | 
2647  | 0  |     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));  | 
2648  | 0  |     if (cur == NULL) { | 
2649  | 0  |   xmlTreeErrMemory("building reference"); | 
2650  | 0  |   return(NULL);  | 
2651  | 0  |     }  | 
2652  | 0  |     memset(cur, 0, sizeof(xmlNode));  | 
2653  | 0  |     cur->type = XML_ENTITY_REF_NODE;  | 
2654  |  | 
  | 
2655  | 0  |     cur->doc = (xmlDoc *)doc;  | 
2656  | 0  |     if (name[0] == '&') { | 
2657  | 0  |         int len;  | 
2658  | 0  |         name++;  | 
2659  | 0  |   len = xmlStrlen(name);  | 
2660  | 0  |   if (name[len - 1] == ';')  | 
2661  | 0  |       cur->name = xmlStrndup(name, len - 1);  | 
2662  | 0  |   else  | 
2663  | 0  |       cur->name = xmlStrndup(name, len);  | 
2664  | 0  |     } else  | 
2665  | 0  |   cur->name = xmlStrdup(name);  | 
2666  |  | 
  | 
2667  | 0  |     ent = xmlGetDocEntity(doc, cur->name);  | 
2668  | 0  |     if (ent != NULL) { | 
2669  | 0  |   cur->content = ent->content;  | 
2670  |  |   /*  | 
2671  |  |    * The parent pointer in entity is a DTD pointer and thus is NOT  | 
2672  |  |    * updated.  Not sure if this is 100% correct.  | 
2673  |  |    *  -George  | 
2674  |  |    */  | 
2675  | 0  |   cur->children = (xmlNodePtr) ent;  | 
2676  | 0  |   cur->last = (xmlNodePtr) ent;  | 
2677  | 0  |     }  | 
2678  |  | 
  | 
2679  | 0  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
2680  | 0  |   xmlRegisterNodeDefaultValue(cur);  | 
2681  | 0  |     return(cur);  | 
2682  | 0  | }  | 
2683  |  |  | 
2684  |  | /**  | 
2685  |  |  * xmlNewDocText:  | 
2686  |  |  * @doc: the document  | 
2687  |  |  * @content:  the text content  | 
2688  |  |  *  | 
2689  |  |  * Creation of a new text node within a document.  | 
2690  |  |  * Returns a pointer to the new node object.  | 
2691  |  |  */  | 
2692  |  | xmlNodePtr  | 
2693  | 3.70M  | xmlNewDocText(const xmlDoc *doc, const xmlChar *content) { | 
2694  | 3.70M  |     xmlNodePtr cur;  | 
2695  |  |  | 
2696  | 3.70M  |     cur = xmlNewText(content);  | 
2697  | 3.70M  |     if (cur != NULL) cur->doc = (xmlDoc *)doc;  | 
2698  | 3.70M  |     return(cur);  | 
2699  | 3.70M  | }  | 
2700  |  |  | 
2701  |  | /**  | 
2702  |  |  * xmlNewTextLen:  | 
2703  |  |  * @content:  the text content  | 
2704  |  |  * @len:  the text len.  | 
2705  |  |  *  | 
2706  |  |  * Use of this function is DISCOURAGED in favor of xmlNewDocTextLen.  | 
2707  |  |  *  | 
2708  |  |  * Creation of a new text node with an extra parameter for the content's length  | 
2709  |  |  * Returns a pointer to the new node object.  | 
2710  |  |  */  | 
2711  |  | xmlNodePtr  | 
2712  | 8.63k  | xmlNewTextLen(const xmlChar *content, int len) { | 
2713  | 8.63k  |     xmlNodePtr cur;  | 
2714  |  |  | 
2715  |  |     /*  | 
2716  |  |      * Allocate a new node and fill the fields.  | 
2717  |  |      */  | 
2718  | 8.63k  |     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));  | 
2719  | 8.63k  |     if (cur == NULL) { | 
2720  | 0  |   xmlTreeErrMemory("building text"); | 
2721  | 0  |   return(NULL);  | 
2722  | 0  |     }  | 
2723  | 8.63k  |     memset(cur, 0, sizeof(xmlNode));  | 
2724  | 8.63k  |     cur->type = XML_TEXT_NODE;  | 
2725  |  |  | 
2726  | 8.63k  |     cur->name = xmlStringText;  | 
2727  | 8.63k  |     if (content != NULL) { | 
2728  | 8.63k  |   cur->content = xmlStrndup(content, len);  | 
2729  | 8.63k  |     }  | 
2730  |  |  | 
2731  | 8.63k  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
2732  | 0  |   xmlRegisterNodeDefaultValue(cur);  | 
2733  | 8.63k  |     return(cur);  | 
2734  | 8.63k  | }  | 
2735  |  |  | 
2736  |  | /**  | 
2737  |  |  * xmlNewDocTextLen:  | 
2738  |  |  * @doc: the document  | 
2739  |  |  * @content:  the text content  | 
2740  |  |  * @len:  the text len.  | 
2741  |  |  *  | 
2742  |  |  * Creation of a new text node with an extra content length parameter. The  | 
2743  |  |  * text node pertain to a given document.  | 
2744  |  |  * Returns a pointer to the new node object.  | 
2745  |  |  */  | 
2746  |  | xmlNodePtr  | 
2747  | 0  | xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) { | 
2748  | 0  |     xmlNodePtr cur;  | 
2749  |  | 
  | 
2750  | 0  |     cur = xmlNewTextLen(content, len);  | 
2751  | 0  |     if (cur != NULL) cur->doc = doc;  | 
2752  | 0  |     return(cur);  | 
2753  | 0  | }  | 
2754  |  |  | 
2755  |  | /**  | 
2756  |  |  * xmlNewComment:  | 
2757  |  |  * @content:  the comment content  | 
2758  |  |  *  | 
2759  |  |  * Use of this function is DISCOURAGED in favor of xmlNewDocComment.  | 
2760  |  |  *  | 
2761  |  |  * Creation of a new node containing a comment.  | 
2762  |  |  * Returns a pointer to the new node object.  | 
2763  |  |  */  | 
2764  |  | xmlNodePtr  | 
2765  | 7.40k  | xmlNewComment(const xmlChar *content) { | 
2766  | 7.40k  |     xmlNodePtr cur;  | 
2767  |  |  | 
2768  |  |     /*  | 
2769  |  |      * Allocate a new node and fill the fields.  | 
2770  |  |      */  | 
2771  | 7.40k  |     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));  | 
2772  | 7.40k  |     if (cur == NULL) { | 
2773  | 0  |   xmlTreeErrMemory("building comment"); | 
2774  | 0  |   return(NULL);  | 
2775  | 0  |     }  | 
2776  | 7.40k  |     memset(cur, 0, sizeof(xmlNode));  | 
2777  | 7.40k  |     cur->type = XML_COMMENT_NODE;  | 
2778  |  |  | 
2779  | 7.40k  |     cur->name = xmlStringComment;  | 
2780  | 7.40k  |     if (content != NULL) { | 
2781  | 7.40k  |   cur->content = xmlStrdup(content);  | 
2782  | 7.40k  |     }  | 
2783  |  |  | 
2784  | 7.40k  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
2785  | 0  |   xmlRegisterNodeDefaultValue(cur);  | 
2786  | 7.40k  |     return(cur);  | 
2787  | 7.40k  | }  | 
2788  |  |  | 
2789  |  | /**  | 
2790  |  |  * xmlNewCDataBlock:  | 
2791  |  |  * @doc:  the document  | 
2792  |  |  * @content:  the CDATA block content content  | 
2793  |  |  * @len:  the length of the block  | 
2794  |  |  *  | 
2795  |  |  * Creation of a new node containing a CDATA block.  | 
2796  |  |  * Returns a pointer to the new node object.  | 
2797  |  |  */  | 
2798  |  | xmlNodePtr  | 
2799  | 3.70k  | xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) { | 
2800  | 3.70k  |     xmlNodePtr cur;  | 
2801  |  |  | 
2802  |  |     /*  | 
2803  |  |      * Allocate a new node and fill the fields.  | 
2804  |  |      */  | 
2805  | 3.70k  |     cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));  | 
2806  | 3.70k  |     if (cur == NULL) { | 
2807  | 0  |   xmlTreeErrMemory("building CDATA"); | 
2808  | 0  |   return(NULL);  | 
2809  | 0  |     }  | 
2810  | 3.70k  |     memset(cur, 0, sizeof(xmlNode));  | 
2811  | 3.70k  |     cur->type = XML_CDATA_SECTION_NODE;  | 
2812  | 3.70k  |     cur->doc = doc;  | 
2813  |  |  | 
2814  | 3.70k  |     if (content != NULL) { | 
2815  | 3.70k  |   cur->content = xmlStrndup(content, len);  | 
2816  | 3.70k  |     }  | 
2817  |  |  | 
2818  | 3.70k  |     if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
2819  | 0  |   xmlRegisterNodeDefaultValue(cur);  | 
2820  | 3.70k  |     return(cur);  | 
2821  | 3.70k  | }  | 
2822  |  |  | 
2823  |  | /**  | 
2824  |  |  * xmlNewDocComment:  | 
2825  |  |  * @doc:  the document  | 
2826  |  |  * @content:  the comment content  | 
2827  |  |  *  | 
2828  |  |  * Creation of a new node containing a comment within a document.  | 
2829  |  |  * Returns a pointer to the new node object.  | 
2830  |  |  */  | 
2831  |  | xmlNodePtr  | 
2832  | 7.40k  | xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) { | 
2833  | 7.40k  |     xmlNodePtr cur;  | 
2834  |  |  | 
2835  | 7.40k  |     cur = xmlNewComment(content);  | 
2836  | 7.40k  |     if (cur != NULL) cur->doc = doc;  | 
2837  | 7.40k  |     return(cur);  | 
2838  | 7.40k  | }  | 
2839  |  |  | 
2840  | 17.2k  | static const xmlChar *_copyStringForNewDictIfNeeded(xmlDictPtr oldDict, xmlDictPtr newDict, const xmlChar *oldValue) { | 
2841  | 17.2k  |     const xmlChar *newValue = oldValue;  | 
2842  | 17.2k  |     if (oldValue) { | 
2843  | 17.2k  |         int oldDictOwnsOldValue = oldDict && (xmlDictOwns(oldDict, oldValue) == 1);  | 
2844  | 17.2k  |         if (oldDictOwnsOldValue) { | 
2845  | 0  |             if (newDict)  | 
2846  | 0  |                 newValue = xmlDictLookup(newDict, oldValue, -1);  | 
2847  | 0  |             else  | 
2848  | 0  |                 newValue = xmlStrdup(oldValue);  | 
2849  | 0  |         }  | 
2850  | 17.2k  |     }  | 
2851  | 17.2k  |     return newValue;  | 
2852  | 17.2k  | }  | 
2853  |  |  | 
2854  |  | /**  | 
2855  |  |  * xmlSetTreeDoc:  | 
2856  |  |  * @tree:  the top element  | 
2857  |  |  * @doc:  the document  | 
2858  |  |  *  | 
2859  |  |  * update all nodes under the tree to point to the right document  | 
2860  |  |  */  | 
2861  |  | void  | 
2862  | 8.63k  | xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) { | 
2863  | 8.63k  |     xmlAttrPtr prop;  | 
2864  |  |  | 
2865  | 8.63k  |     if ((tree == NULL) || (tree->type == XML_NAMESPACE_DECL))  | 
2866  | 0  |   return;  | 
2867  | 8.63k  |     if (tree->doc != doc) { | 
2868  | 8.63k  |         xmlDictPtr oldTreeDict = tree->doc ? tree->doc->dict : NULL;  | 
2869  | 8.63k  |         xmlDictPtr newDict = doc ? doc->dict : NULL;  | 
2870  |  |  | 
2871  | 8.63k  |   if(tree->type == XML_ELEMENT_NODE) { | 
2872  | 0  |       prop = tree->properties;  | 
2873  | 0  |       while (prop != NULL) { | 
2874  | 0  |                 if (prop->atype == XML_ATTRIBUTE_ID) { | 
2875  | 0  |                     xmlRemoveID(tree->doc, prop);  | 
2876  | 0  |                 }  | 
2877  |  | 
  | 
2878  | 0  |                 if (prop->doc != doc) { | 
2879  | 0  |                     xmlDictPtr oldPropDict = prop->doc ? prop->doc->dict : NULL;  | 
2880  | 0  |                     prop->name = _copyStringForNewDictIfNeeded(oldPropDict, newDict, prop->name);  | 
2881  | 0  |                     prop->doc = doc;  | 
2882  | 0  |                 }  | 
2883  | 0  |     xmlSetListDoc(prop->children, doc);  | 
2884  |  |  | 
2885  |  |                 /*  | 
2886  |  |                  * TODO: ID attributes should be also added to the new  | 
2887  |  |                  * document, but this breaks things like xmlReplaceNode.  | 
2888  |  |                  * The underlying problem is that xmlRemoveID is only called  | 
2889  |  |                  * if a node is destroyed, not if it's unlinked.  | 
2890  |  |                  */  | 
2891  |  | #if 0  | 
2892  |  |                 if (xmlIsID(doc, tree, prop)) { | 
2893  |  |                     xmlChar *idVal = xmlNodeListGetString(doc, prop->children,  | 
2894  |  |                                                           1);  | 
2895  |  |                     xmlAddID(NULL, doc, idVal, prop);  | 
2896  |  |                 }  | 
2897  |  | #endif  | 
2898  |  | 
  | 
2899  | 0  |     prop = prop->next;  | 
2900  | 0  |       }  | 
2901  | 0  |   }  | 
2902  | 8.63k  |         if (tree->type == XML_ENTITY_REF_NODE) { | 
2903  |  |             /*  | 
2904  |  |              * Clear 'children' which points to the entity declaration  | 
2905  |  |              * from the original document.  | 
2906  |  |              */  | 
2907  | 0  |             tree->children = NULL;  | 
2908  | 8.63k  |         } else if (tree->children != NULL) { | 
2909  | 0  |       xmlSetListDoc(tree->children, doc);  | 
2910  | 0  |         }  | 
2911  |  |  | 
2912  | 8.63k  |         tree->name = _copyStringForNewDictIfNeeded(oldTreeDict, newDict, tree->name);  | 
2913  | 8.63k  |         tree->content = (xmlChar *)_copyStringForNewDictIfNeeded(oldTreeDict, NULL, tree->content);  | 
2914  |  |         /* FIXME: tree->ns should be updated as in xmlStaticCopyNode(). */  | 
2915  | 8.63k  |   tree->doc = doc;  | 
2916  | 8.63k  |     }  | 
2917  | 8.63k  | }  | 
2918  |  |  | 
2919  |  | /**  | 
2920  |  |  * xmlSetListDoc:  | 
2921  |  |  * @list:  the first element  | 
2922  |  |  * @doc:  the document  | 
2923  |  |  *  | 
2924  |  |  * update all nodes in the list to point to the right document  | 
2925  |  |  */  | 
2926  |  | void  | 
2927  | 0  | xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc) { | 
2928  | 0  |     xmlNodePtr cur;  | 
2929  |  | 
  | 
2930  | 0  |     if ((list == NULL) || (list->type == XML_NAMESPACE_DECL))  | 
2931  | 0  |   return;  | 
2932  | 0  |     cur = list;  | 
2933  | 0  |     while (cur != NULL) { | 
2934  | 0  |   if (cur->doc != doc)  | 
2935  | 0  |       xmlSetTreeDoc(cur, doc);  | 
2936  | 0  |   cur = cur->next;  | 
2937  | 0  |     }  | 
2938  | 0  | }  | 
2939  |  |  | 
2940  |  | #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)  | 
2941  |  | /**  | 
2942  |  |  * xmlNewChild:  | 
2943  |  |  * @parent:  the parent node  | 
2944  |  |  * @ns:  a namespace if any  | 
2945  |  |  * @name:  the name of the child  | 
2946  |  |  * @content:  the XML content of the child if any.  | 
2947  |  |  *  | 
2948  |  |  * Creation of a new child element, added at the end of @parent children list.  | 
2949  |  |  * @ns and @content parameters are optional (NULL). If @ns is NULL, the newly  | 
2950  |  |  * created element inherits the namespace of @parent. If @content is non NULL,  | 
2951  |  |  * a child list containing the TEXTs and ENTITY_REFs node will be created.  | 
2952  |  |  * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity  | 
2953  |  |  *       references. XML special chars must be escaped first by using  | 
2954  |  |  *       xmlEncodeEntitiesReentrant(), or xmlNewTextChild() should be used.  | 
2955  |  |  *  | 
2956  |  |  * Returns a pointer to the new node object.  | 
2957  |  |  */  | 
2958  |  | xmlNodePtr  | 
2959  |  | xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,  | 
2960  | 0  |             const xmlChar *name, const xmlChar *content) { | 
2961  | 0  |     xmlNodePtr cur, prev;  | 
2962  |  | 
  | 
2963  | 0  |     if (parent == NULL) { | 
2964  |  | #ifdef DEBUG_TREE  | 
2965  |  |         xmlGenericError(xmlGenericErrorContext,  | 
2966  |  |     "xmlNewChild : parent == NULL\n");  | 
2967  |  | #endif  | 
2968  | 0  |   return(NULL);  | 
2969  | 0  |     }  | 
2970  |  |  | 
2971  | 0  |     if (name == NULL) { | 
2972  |  | #ifdef DEBUG_TREE  | 
2973  |  |         xmlGenericError(xmlGenericErrorContext,  | 
2974  |  |     "xmlNewChild : name == NULL\n");  | 
2975  |  | #endif  | 
2976  | 0  |   return(NULL);  | 
2977  | 0  |     }  | 
2978  |  |  | 
2979  |  |     /*  | 
2980  |  |      * Allocate a new node  | 
2981  |  |      */  | 
2982  | 0  |     if (parent->type == XML_ELEMENT_NODE) { | 
2983  | 0  |   if (ns == NULL)  | 
2984  | 0  |       cur = xmlNewDocNode(parent->doc, parent->ns, name, content);  | 
2985  | 0  |   else  | 
2986  | 0  |       cur = xmlNewDocNode(parent->doc, ns, name, content);  | 
2987  | 0  |     } else if ((parent->type == XML_DOCUMENT_NODE) ||  | 
2988  | 0  |          (parent->type == XML_HTML_DOCUMENT_NODE)) { | 
2989  | 0  |   if (ns == NULL)  | 
2990  | 0  |       cur = xmlNewDocNode((xmlDocPtr) parent, NULL, name, content);  | 
2991  | 0  |   else  | 
2992  | 0  |       cur = xmlNewDocNode((xmlDocPtr) parent, ns, name, content);  | 
2993  | 0  |     } else if (parent->type == XML_DOCUMENT_FRAG_NODE) { | 
2994  | 0  |       cur = xmlNewDocNode( parent->doc, ns, name, content);  | 
2995  | 0  |     } else { | 
2996  | 0  |   return(NULL);  | 
2997  | 0  |     }  | 
2998  | 0  |     if (cur == NULL) return(NULL);  | 
2999  |  |  | 
3000  |  |     /*  | 
3001  |  |      * add the new element at the end of the children list.  | 
3002  |  |      */  | 
3003  | 0  |     cur->type = XML_ELEMENT_NODE;  | 
3004  | 0  |     cur->parent = parent;  | 
3005  | 0  |     cur->doc = parent->doc;  | 
3006  | 0  |     if (parent->children == NULL) { | 
3007  | 0  |         parent->children = cur;  | 
3008  | 0  |   parent->last = cur;  | 
3009  | 0  |     } else { | 
3010  | 0  |         prev = parent->last;  | 
3011  | 0  |   prev->next = cur;  | 
3012  | 0  |   cur->prev = prev;  | 
3013  | 0  |   parent->last = cur;  | 
3014  | 0  |     }  | 
3015  |  | 
  | 
3016  | 0  |     return(cur);  | 
3017  | 0  | }  | 
3018  |  | #endif /* LIBXML_TREE_ENABLED */  | 
3019  |  |  | 
3020  |  | /**  | 
3021  |  |  * xmlAddPropSibling:  | 
3022  |  |  * @prev:  the attribute to which @prop is added after  | 
3023  |  |  * @cur:   the base attribute passed to calling function  | 
3024  |  |  * @prop:  the new attribute  | 
3025  |  |  *  | 
3026  |  |  * Add a new attribute after @prev using @cur as base attribute.  | 
3027  |  |  * When inserting before @cur, @prev is passed as @cur->prev.  | 
3028  |  |  * When inserting after @cur, @prev is passed as @cur.  | 
3029  |  |  * If an existing attribute is found it is destroyed prior to adding @prop.  | 
3030  |  |  *  | 
3031  |  |  * See the note regarding namespaces in xmlAddChild.  | 
3032  |  |  *  | 
3033  |  |  * Returns the attribute being inserted or NULL in case of error.  | 
3034  |  |  */  | 
3035  |  | static xmlNodePtr  | 
3036  | 0  | xmlAddPropSibling(xmlNodePtr prev, xmlNodePtr cur, xmlNodePtr prop) { | 
3037  | 0  |   xmlAttrPtr attr;  | 
3038  |  | 
  | 
3039  | 0  |   if ((cur == NULL) || (cur->type != XML_ATTRIBUTE_NODE) ||  | 
3040  | 0  |       (prop == NULL) || (prop->type != XML_ATTRIBUTE_NODE) ||  | 
3041  | 0  |       ((prev != NULL) && (prev->type != XML_ATTRIBUTE_NODE)))  | 
3042  | 0  |     return(NULL);  | 
3043  |  |  | 
3044  |  |   /* check if an attribute with the same name exists */  | 
3045  | 0  |   if (prop->ns == NULL)  | 
3046  | 0  |     attr = xmlHasNsProp(cur->parent, prop->name, NULL);  | 
3047  | 0  |   else  | 
3048  | 0  |     attr = xmlHasNsProp(cur->parent, prop->name, prop->ns->href);  | 
3049  |  | 
  | 
3050  | 0  |   if (prop->doc != cur->doc) { | 
3051  | 0  |     xmlSetTreeDoc(prop, cur->doc);  | 
3052  | 0  |   }  | 
3053  | 0  |   prop->parent = cur->parent;  | 
3054  | 0  |   prop->prev = prev;  | 
3055  | 0  |   if (prev != NULL) { | 
3056  | 0  |     prop->next = prev->next;  | 
3057  | 0  |     prev->next = prop;  | 
3058  | 0  |     if (prop->next)  | 
3059  | 0  |       prop->next->prev = prop;  | 
3060  | 0  |   } else { | 
3061  | 0  |     prop->next = cur;  | 
3062  | 0  |     cur->prev = prop;  | 
3063  | 0  |   }  | 
3064  | 0  |   if (prop->prev == NULL && prop->parent != NULL)  | 
3065  | 0  |     prop->parent->properties = (xmlAttrPtr) prop;  | 
3066  | 0  |   if ((attr != NULL) && (attr->type != XML_ATTRIBUTE_DECL)) { | 
3067  |  |     /* different instance, destroy it (attributes must be unique) */  | 
3068  | 0  |     xmlRemoveProp((xmlAttrPtr) attr);  | 
3069  | 0  |   }  | 
3070  | 0  |   return prop;  | 
3071  | 0  | }  | 
3072  |  |  | 
3073  |  | /**  | 
3074  |  |  * xmlAddNextSibling:  | 
3075  |  |  * @cur:  the child node  | 
3076  |  |  * @elem:  the new node  | 
3077  |  |  *  | 
3078  |  |  * Add a new node @elem as the next sibling of @cur  | 
3079  |  |  * If the new node was already inserted in a document it is  | 
3080  |  |  * first unlinked from its existing context.  | 
3081  |  |  * As a result of text merging @elem may be freed.  | 
3082  |  |  * If the new node is ATTRIBUTE, it is added into properties instead of children.  | 
3083  |  |  * If there is an attribute with equal name, it is first destroyed.  | 
3084  |  |  *  | 
3085  |  |  * See the note regarding namespaces in xmlAddChild.  | 
3086  |  |  *  | 
3087  |  |  * Returns the new node or NULL in case of error.  | 
3088  |  |  */  | 
3089  |  | xmlNodePtr  | 
3090  | 0  | xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) { | 
3091  | 0  |     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { | 
3092  |  | #ifdef DEBUG_TREE  | 
3093  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3094  |  |     "xmlAddNextSibling : cur == NULL\n");  | 
3095  |  | #endif  | 
3096  | 0  |   return(NULL);  | 
3097  | 0  |     }  | 
3098  | 0  |     if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) { | 
3099  |  | #ifdef DEBUG_TREE  | 
3100  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3101  |  |     "xmlAddNextSibling : elem == NULL\n");  | 
3102  |  | #endif  | 
3103  | 0  |   return(NULL);  | 
3104  | 0  |     }  | 
3105  |  |  | 
3106  | 0  |     if (cur == elem) { | 
3107  |  | #ifdef DEBUG_TREE  | 
3108  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3109  |  |     "xmlAddNextSibling : cur == elem\n");  | 
3110  |  | #endif  | 
3111  | 0  |   return(NULL);  | 
3112  | 0  |     }  | 
3113  |  |  | 
3114  | 0  |     xmlUnlinkNode(elem);  | 
3115  |  | 
  | 
3116  | 0  |     if (elem->type == XML_TEXT_NODE) { | 
3117  | 0  |   if (cur->type == XML_TEXT_NODE) { | 
3118  | 0  |       xmlNodeAddContent(cur, elem->content);  | 
3119  | 0  |       xmlFreeNode(elem);  | 
3120  | 0  |       return(cur);  | 
3121  | 0  |   }  | 
3122  | 0  |   if ((cur->next != NULL) && (cur->next->type == XML_TEXT_NODE) &&  | 
3123  | 0  |             (cur->name == cur->next->name)) { | 
3124  | 0  |       xmlChar *tmp;  | 
3125  |  | 
  | 
3126  | 0  |       tmp = xmlStrdup(elem->content);  | 
3127  | 0  |       tmp = xmlStrcat(tmp, cur->next->content);  | 
3128  | 0  |       xmlNodeSetContent(cur->next, tmp);  | 
3129  | 0  |       xmlFree(tmp);  | 
3130  | 0  |       xmlFreeNode(elem);  | 
3131  | 0  |       return(cur->next);  | 
3132  | 0  |   }  | 
3133  | 0  |     } else if (elem->type == XML_ATTRIBUTE_NODE) { | 
3134  | 0  |     return xmlAddPropSibling(cur, cur, elem);  | 
3135  | 0  |     }  | 
3136  |  |  | 
3137  | 0  |     if (elem->doc != cur->doc) { | 
3138  | 0  |   xmlSetTreeDoc(elem, cur->doc);  | 
3139  | 0  |     }  | 
3140  | 0  |     elem->parent = cur->parent;  | 
3141  | 0  |     elem->prev = cur;  | 
3142  | 0  |     elem->next = cur->next;  | 
3143  | 0  |     cur->next = elem;  | 
3144  | 0  |     if (elem->next != NULL)  | 
3145  | 0  |   elem->next->prev = elem;  | 
3146  | 0  |     if ((elem->parent != NULL) && (elem->parent->last == cur))  | 
3147  | 0  |   elem->parent->last = elem;  | 
3148  | 0  |     return(elem);  | 
3149  | 0  | }  | 
3150  |  |  | 
3151  |  | #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \  | 
3152  |  |     defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)  | 
3153  |  | /**  | 
3154  |  |  * xmlAddPrevSibling:  | 
3155  |  |  * @cur:  the child node  | 
3156  |  |  * @elem:  the new node  | 
3157  |  |  *  | 
3158  |  |  * Add a new node @elem as the previous sibling of @cur  | 
3159  |  |  * merging adjacent TEXT nodes (@elem may be freed)  | 
3160  |  |  * If the new node was already inserted in a document it is  | 
3161  |  |  * first unlinked from its existing context.  | 
3162  |  |  * If the new node is ATTRIBUTE, it is added into properties instead of children.  | 
3163  |  |  * If there is an attribute with equal name, it is first destroyed.  | 
3164  |  |  *  | 
3165  |  |  * See the note regarding namespaces in xmlAddChild.  | 
3166  |  |  *  | 
3167  |  |  * Returns the new node or NULL in case of error.  | 
3168  |  |  */  | 
3169  |  | xmlNodePtr  | 
3170  | 0  | xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) { | 
3171  | 0  |     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { | 
3172  |  | #ifdef DEBUG_TREE  | 
3173  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3174  |  |     "xmlAddPrevSibling : cur == NULL\n");  | 
3175  |  | #endif  | 
3176  | 0  |   return(NULL);  | 
3177  | 0  |     }  | 
3178  | 0  |     if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) { | 
3179  |  | #ifdef DEBUG_TREE  | 
3180  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3181  |  |     "xmlAddPrevSibling : elem == NULL\n");  | 
3182  |  | #endif  | 
3183  | 0  |   return(NULL);  | 
3184  | 0  |     }  | 
3185  |  |  | 
3186  | 0  |     if (cur == elem) { | 
3187  |  | #ifdef DEBUG_TREE  | 
3188  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3189  |  |     "xmlAddPrevSibling : cur == elem\n");  | 
3190  |  | #endif  | 
3191  | 0  |   return(NULL);  | 
3192  | 0  |     }  | 
3193  |  |  | 
3194  | 0  |     xmlUnlinkNode(elem);  | 
3195  |  | 
  | 
3196  | 0  |     if (elem->type == XML_TEXT_NODE) { | 
3197  | 0  |   if (cur->type == XML_TEXT_NODE) { | 
3198  | 0  |       xmlChar *tmp;  | 
3199  |  | 
  | 
3200  | 0  |       tmp = xmlStrdup(elem->content);  | 
3201  | 0  |       tmp = xmlStrcat(tmp, cur->content);  | 
3202  | 0  |       xmlNodeSetContent(cur, tmp);  | 
3203  | 0  |       xmlFree(tmp);  | 
3204  | 0  |       xmlFreeNode(elem);  | 
3205  | 0  |       return(cur);  | 
3206  | 0  |   }  | 
3207  | 0  |   if ((cur->prev != NULL) && (cur->prev->type == XML_TEXT_NODE) &&  | 
3208  | 0  |             (cur->name == cur->prev->name)) { | 
3209  | 0  |       xmlNodeAddContent(cur->prev, elem->content);  | 
3210  | 0  |       xmlFreeNode(elem);  | 
3211  | 0  |       return(cur->prev);  | 
3212  | 0  |   }  | 
3213  | 0  |     } else if (elem->type == XML_ATTRIBUTE_NODE) { | 
3214  | 0  |     return xmlAddPropSibling(cur->prev, cur, elem);  | 
3215  | 0  |     }  | 
3216  |  |  | 
3217  | 0  |     if (elem->doc != cur->doc) { | 
3218  | 0  |   xmlSetTreeDoc(elem, cur->doc);  | 
3219  | 0  |     }  | 
3220  | 0  |     elem->parent = cur->parent;  | 
3221  | 0  |     elem->next = cur;  | 
3222  | 0  |     elem->prev = cur->prev;  | 
3223  | 0  |     cur->prev = elem;  | 
3224  | 0  |     if (elem->prev != NULL)  | 
3225  | 0  |   elem->prev->next = elem;  | 
3226  | 0  |     if ((elem->parent != NULL) && (elem->parent->children == cur)) { | 
3227  | 0  |     elem->parent->children = elem;  | 
3228  | 0  |     }  | 
3229  | 0  |     return(elem);  | 
3230  | 0  | }  | 
3231  |  | #endif /* LIBXML_TREE_ENABLED */  | 
3232  |  |  | 
3233  |  | /**  | 
3234  |  |  * xmlAddSibling:  | 
3235  |  |  * @cur:  the child node  | 
3236  |  |  * @elem:  the new node  | 
3237  |  |  *  | 
3238  |  |  * Add a new element @elem to the list of siblings of @cur  | 
3239  |  |  * merging adjacent TEXT nodes (@elem may be freed)  | 
3240  |  |  * If the new element was already inserted in a document it is  | 
3241  |  |  * first unlinked from its existing context.  | 
3242  |  |  *  | 
3243  |  |  * See the note regarding namespaces in xmlAddChild.  | 
3244  |  |  *  | 
3245  |  |  * Returns the new element or NULL in case of error.  | 
3246  |  |  */  | 
3247  |  | xmlNodePtr  | 
3248  | 0  | xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) { | 
3249  | 0  |     xmlNodePtr parent;  | 
3250  |  | 
  | 
3251  | 0  |     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { | 
3252  |  | #ifdef DEBUG_TREE  | 
3253  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3254  |  |     "xmlAddSibling : cur == NULL\n");  | 
3255  |  | #endif  | 
3256  | 0  |   return(NULL);  | 
3257  | 0  |     }  | 
3258  |  |  | 
3259  | 0  |     if ((elem == NULL) || (elem->type == XML_NAMESPACE_DECL)) { | 
3260  |  | #ifdef DEBUG_TREE  | 
3261  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3262  |  |     "xmlAddSibling : elem == NULL\n");  | 
3263  |  | #endif  | 
3264  | 0  |   return(NULL);  | 
3265  | 0  |     }  | 
3266  |  |  | 
3267  | 0  |     if (cur == elem) { | 
3268  |  | #ifdef DEBUG_TREE  | 
3269  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3270  |  |     "xmlAddSibling : cur == elem\n");  | 
3271  |  | #endif  | 
3272  | 0  |   return(NULL);  | 
3273  | 0  |     }  | 
3274  |  |  | 
3275  |  |     /*  | 
3276  |  |      * Constant time is we can rely on the ->parent->last to find  | 
3277  |  |      * the last sibling.  | 
3278  |  |      */  | 
3279  | 0  |     if ((cur->type != XML_ATTRIBUTE_NODE) && (cur->parent != NULL) &&  | 
3280  | 0  |   (cur->parent->children != NULL) &&  | 
3281  | 0  |   (cur->parent->last != NULL) &&  | 
3282  | 0  |   (cur->parent->last->next == NULL)) { | 
3283  | 0  |   cur = cur->parent->last;  | 
3284  | 0  |     } else { | 
3285  | 0  |   while (cur->next != NULL) cur = cur->next;  | 
3286  | 0  |     }  | 
3287  |  | 
  | 
3288  | 0  |     xmlUnlinkNode(elem);  | 
3289  |  | 
  | 
3290  | 0  |     if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE) &&  | 
3291  | 0  |         (cur->name == elem->name)) { | 
3292  | 0  |   xmlNodeAddContent(cur, elem->content);  | 
3293  | 0  |   xmlFreeNode(elem);  | 
3294  | 0  |   return(cur);  | 
3295  | 0  |     } else if (elem->type == XML_ATTRIBUTE_NODE) { | 
3296  | 0  |     return xmlAddPropSibling(cur, cur, elem);  | 
3297  | 0  |     }  | 
3298  |  |  | 
3299  | 0  |     if (elem->doc != cur->doc) { | 
3300  | 0  |   xmlSetTreeDoc(elem, cur->doc);  | 
3301  | 0  |     }  | 
3302  | 0  |     parent = cur->parent;  | 
3303  | 0  |     elem->prev = cur;  | 
3304  | 0  |     elem->next = NULL;  | 
3305  | 0  |     elem->parent = parent;  | 
3306  | 0  |     cur->next = elem;  | 
3307  | 0  |     if (parent != NULL)  | 
3308  | 0  |   parent->last = elem;  | 
3309  |  | 
  | 
3310  | 0  |     return(elem);  | 
3311  | 0  | }  | 
3312  |  |  | 
3313  |  | /**  | 
3314  |  |  * xmlAddChildList:  | 
3315  |  |  * @parent:  the parent node  | 
3316  |  |  * @cur:  the first node in the list  | 
3317  |  |  *  | 
3318  |  |  * Add a list of node at the end of the child list of the parent  | 
3319  |  |  * merging adjacent TEXT nodes (@cur may be freed)  | 
3320  |  |  *  | 
3321  |  |  * See the note regarding namespaces in xmlAddChild.  | 
3322  |  |  *  | 
3323  |  |  * Returns the last child or NULL in case of error.  | 
3324  |  |  */  | 
3325  |  | xmlNodePtr  | 
3326  | 0  | xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) { | 
3327  | 0  |     xmlNodePtr prev;  | 
3328  |  | 
  | 
3329  | 0  |     if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) { | 
3330  |  | #ifdef DEBUG_TREE  | 
3331  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3332  |  |     "xmlAddChildList : parent == NULL\n");  | 
3333  |  | #endif  | 
3334  | 0  |   return(NULL);  | 
3335  | 0  |     }  | 
3336  |  |  | 
3337  | 0  |     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { | 
3338  |  | #ifdef DEBUG_TREE  | 
3339  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3340  |  |     "xmlAddChildList : child == NULL\n");  | 
3341  |  | #endif  | 
3342  | 0  |   return(NULL);  | 
3343  | 0  |     }  | 
3344  |  |  | 
3345  | 0  |     if ((cur->doc != NULL) && (parent->doc != NULL) &&  | 
3346  | 0  |         (cur->doc != parent->doc)) { | 
3347  |  | #ifdef DEBUG_TREE  | 
3348  |  |   xmlGenericError(xmlGenericErrorContext,  | 
3349  |  |     "Elements moved to a different document\n");  | 
3350  |  | #endif  | 
3351  | 0  |     }  | 
3352  |  |  | 
3353  |  |     /*  | 
3354  |  |      * add the first element at the end of the children list.  | 
3355  |  |      */  | 
3356  |  | 
  | 
3357  | 0  |     if (parent->children == NULL) { | 
3358  | 0  |         parent->children = cur;  | 
3359  | 0  |     } else { | 
3360  |  |   /*  | 
3361  |  |    * If cur and parent->last both are TEXT nodes, then merge them.  | 
3362  |  |    */  | 
3363  | 0  |   if ((cur->type == XML_TEXT_NODE) &&  | 
3364  | 0  |       (parent->last->type == XML_TEXT_NODE) &&  | 
3365  | 0  |       (cur->name == parent->last->name)) { | 
3366  | 0  |       xmlNodeAddContent(parent->last, cur->content);  | 
3367  |  |       /*  | 
3368  |  |        * if it's the only child, nothing more to be done.  | 
3369  |  |        */  | 
3370  | 0  |       if (cur->next == NULL) { | 
3371  | 0  |     xmlFreeNode(cur);  | 
3372  | 0  |     return(parent->last);  | 
3373  | 0  |       }  | 
3374  | 0  |       prev = cur;  | 
3375  | 0  |       cur = cur->next;  | 
3376  | 0  |       xmlFreeNode(prev);  | 
3377  | 0  |   }  | 
3378  | 0  |         prev = parent->last;  | 
3379  | 0  |   prev->next = cur;  | 
3380  | 0  |   cur->prev = prev;  | 
3381  | 0  |     }  | 
3382  | 0  |     while (cur->next != NULL) { | 
3383  | 0  |   cur->parent = parent;  | 
3384  | 0  |   if (cur->doc != parent->doc) { | 
3385  | 0  |       xmlSetTreeDoc(cur, parent->doc);  | 
3386  | 0  |   }  | 
3387  | 0  |         cur = cur->next;  | 
3388  | 0  |     }  | 
3389  | 0  |     cur->parent = parent;  | 
3390  |  |     /* the parent may not be linked to a doc ! */  | 
3391  | 0  |     if (cur->doc != parent->doc) { | 
3392  | 0  |         xmlSetTreeDoc(cur, parent->doc);  | 
3393  | 0  |     }  | 
3394  | 0  |     parent->last = cur;  | 
3395  |  | 
  | 
3396  | 0  |     return(cur);  | 
3397  | 0  | }  | 
3398  |  |  | 
3399  |  | /**  | 
3400  |  |  * xmlAddChild:  | 
3401  |  |  * @parent:  the parent node  | 
3402  |  |  * @cur:  the child node  | 
3403  |  |  *  | 
3404  |  |  * Add a new node to @parent, at the end of the child (or property) list  | 
3405  |  |  * merging adjacent TEXT nodes (in which case @cur is freed)  | 
3406  |  |  * If the new node is ATTRIBUTE, it is added into properties instead of children.  | 
3407  |  |  * If there is an attribute with equal name, it is first destroyed.  | 
3408  |  |  *  | 
3409  |  |  * All tree manipulation functions can safely move nodes within a document.  | 
3410  |  |  * But when moving nodes from one document to another, references to  | 
3411  |  |  * namespaces in element or attribute nodes are NOT fixed. In this case,  | 
3412  |  |  * you MUST call xmlReconciliateNs after the move operation to avoid  | 
3413  |  |  * memory errors.  | 
3414  |  |  *  | 
3415  |  |  * Returns the child or NULL in case of error.  | 
3416  |  |  */  | 
3417  |  | xmlNodePtr  | 
3418  | 3.41M  | xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) { | 
3419  | 3.41M  |     xmlNodePtr prev;  | 
3420  |  |  | 
3421  | 3.41M  |     if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) { | 
3422  |  | #ifdef DEBUG_TREE  | 
3423  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3424  |  |     "xmlAddChild : parent == NULL\n");  | 
3425  |  | #endif  | 
3426  | 0  |   return(NULL);  | 
3427  | 0  |     }  | 
3428  |  |  | 
3429  | 3.41M  |     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { | 
3430  |  | #ifdef DEBUG_TREE  | 
3431  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3432  |  |     "xmlAddChild : child == NULL\n");  | 
3433  |  | #endif  | 
3434  | 0  |   return(NULL);  | 
3435  | 0  |     }  | 
3436  |  |  | 
3437  | 3.41M  |     if (parent == cur) { | 
3438  |  | #ifdef DEBUG_TREE  | 
3439  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3440  |  |     "xmlAddChild : parent == cur\n");  | 
3441  |  | #endif  | 
3442  | 0  |   return(NULL);  | 
3443  | 0  |     }  | 
3444  |  |     /*  | 
3445  |  |      * If cur is a TEXT node, merge its content with adjacent TEXT nodes  | 
3446  |  |      * cur is then freed.  | 
3447  |  |      */  | 
3448  | 3.41M  |     if (cur->type == XML_TEXT_NODE) { | 
3449  | 60.5k  |   if ((parent->type == XML_TEXT_NODE) &&  | 
3450  | 60.5k  |       (parent->content != NULL) &&  | 
3451  | 60.5k  |       (parent->name == cur->name)) { | 
3452  | 0  |       xmlNodeAddContent(parent, cur->content);  | 
3453  | 0  |       xmlFreeNode(cur);  | 
3454  | 0  |       return(parent);  | 
3455  | 0  |   }  | 
3456  | 60.5k  |   if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) &&  | 
3457  | 60.5k  |       (parent->last->name == cur->name) &&  | 
3458  | 60.5k  |       (parent->last != cur)) { | 
3459  | 0  |       xmlNodeAddContent(parent->last, cur->content);  | 
3460  | 0  |       xmlFreeNode(cur);  | 
3461  | 0  |       return(parent->last);  | 
3462  | 0  |   }  | 
3463  | 60.5k  |     }  | 
3464  |  |  | 
3465  |  |     /*  | 
3466  |  |      * add the new element at the end of the children list.  | 
3467  |  |      */  | 
3468  | 3.41M  |     prev = cur->parent;  | 
3469  | 3.41M  |     cur->parent = parent;  | 
3470  | 3.41M  |     if (cur->doc != parent->doc) { | 
3471  | 8.63k  |   xmlSetTreeDoc(cur, parent->doc);  | 
3472  | 8.63k  |     }  | 
3473  |  |     /* this check prevents a loop on tree-traversions if a developer  | 
3474  |  |      * tries to add a node to its parent multiple times  | 
3475  |  |      */  | 
3476  | 3.41M  |     if (prev == parent)  | 
3477  | 0  |   return(cur);  | 
3478  |  |  | 
3479  |  |     /*  | 
3480  |  |      * Coalescing  | 
3481  |  |      */  | 
3482  | 3.41M  |     if ((parent->type == XML_TEXT_NODE) &&  | 
3483  | 3.41M  |   (parent->content != NULL) &&  | 
3484  | 3.41M  |   (parent != cur)) { | 
3485  | 0  |   xmlNodeAddContent(parent, cur->content);  | 
3486  | 0  |   xmlFreeNode(cur);  | 
3487  | 0  |   return(parent);  | 
3488  | 0  |     }  | 
3489  | 3.41M  |     if (cur->type == XML_ATTRIBUTE_NODE) { | 
3490  | 0  |     if (parent->type != XML_ELEMENT_NODE)  | 
3491  | 0  |       return(NULL);  | 
3492  | 0  |   if (parent->properties != NULL) { | 
3493  |  |       /* check if an attribute with the same name exists */  | 
3494  | 0  |       xmlAttrPtr lastattr;  | 
3495  |  | 
  | 
3496  | 0  |       if (cur->ns == NULL)  | 
3497  | 0  |     lastattr = xmlHasNsProp(parent, cur->name, NULL);  | 
3498  | 0  |       else  | 
3499  | 0  |     lastattr = xmlHasNsProp(parent, cur->name, cur->ns->href);  | 
3500  | 0  |       if ((lastattr != NULL) && (lastattr != (xmlAttrPtr) cur) && (lastattr->type != XML_ATTRIBUTE_DECL)) { | 
3501  |  |     /* different instance, destroy it (attributes must be unique) */  | 
3502  | 0  |       xmlUnlinkNode((xmlNodePtr) lastattr);  | 
3503  | 0  |     xmlFreeProp(lastattr);  | 
3504  | 0  |       }  | 
3505  | 0  |     if (lastattr == (xmlAttrPtr) cur)  | 
3506  | 0  |       return(cur);  | 
3507  |  | 
  | 
3508  | 0  |   }  | 
3509  | 0  |   if (parent->properties == NULL) { | 
3510  | 0  |       parent->properties = (xmlAttrPtr) cur;  | 
3511  | 0  |   } else { | 
3512  |  |       /* find the end */  | 
3513  | 0  |       xmlAttrPtr lastattr = parent->properties;  | 
3514  | 0  |       while (lastattr->next != NULL) { | 
3515  | 0  |     lastattr = lastattr->next;  | 
3516  | 0  |       }  | 
3517  | 0  |       lastattr->next = (xmlAttrPtr) cur;  | 
3518  | 0  |       ((xmlAttrPtr) cur)->prev = lastattr;  | 
3519  | 0  |   }  | 
3520  | 3.41M  |     } else { | 
3521  | 3.41M  |   if (parent->children == NULL) { | 
3522  | 148k  |       parent->children = cur;  | 
3523  | 148k  |       parent->last = cur;  | 
3524  | 3.26M  |   } else { | 
3525  | 3.26M  |       prev = parent->last;  | 
3526  | 3.26M  |       prev->next = cur;  | 
3527  | 3.26M  |       cur->prev = prev;  | 
3528  | 3.26M  |       parent->last = cur;  | 
3529  | 3.26M  |   }  | 
3530  | 3.41M  |     }  | 
3531  | 3.41M  |     return(cur);  | 
3532  | 3.41M  | }  | 
3533  |  |  | 
3534  |  | /**  | 
3535  |  |  * xmlGetLastChild:  | 
3536  |  |  * @parent:  the parent node  | 
3537  |  |  *  | 
3538  |  |  * Search the last child of a node.  | 
3539  |  |  * Returns the last child or NULL if none.  | 
3540  |  |  */  | 
3541  |  | xmlNodePtr  | 
3542  | 0  | xmlGetLastChild(const xmlNode *parent) { | 
3543  | 0  |     if ((parent == NULL) || (parent->type == XML_NAMESPACE_DECL)) { | 
3544  |  | #ifdef DEBUG_TREE  | 
3545  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3546  |  |     "xmlGetLastChild : parent == NULL\n");  | 
3547  |  | #endif  | 
3548  | 0  |   return(NULL);  | 
3549  | 0  |     }  | 
3550  | 0  |     return(parent->last);  | 
3551  | 0  | }  | 
3552  |  |  | 
3553  |  | #ifdef LIBXML_TREE_ENABLED  | 
3554  |  | /*  | 
3555  |  |  * 5 interfaces from DOM ElementTraversal  | 
3556  |  |  */  | 
3557  |  |  | 
3558  |  | /**  | 
3559  |  |  * xmlChildElementCount:  | 
3560  |  |  * @parent: the parent node  | 
3561  |  |  *  | 
3562  |  |  * Finds the current number of child nodes of that element which are  | 
3563  |  |  * element nodes.  | 
3564  |  |  * Note the handling of entities references is different than in  | 
3565  |  |  * the W3C DOM element traversal spec since we don't have back reference  | 
3566  |  |  * from entities content to entities references.  | 
3567  |  |  *  | 
3568  |  |  * Returns the count of element child or 0 if not available  | 
3569  |  |  */  | 
3570  |  | unsigned long  | 
3571  | 0  | xmlChildElementCount(xmlNodePtr parent) { | 
3572  | 0  |     unsigned long ret = 0;  | 
3573  | 0  |     xmlNodePtr cur = NULL;  | 
3574  |  | 
  | 
3575  | 0  |     if (parent == NULL)  | 
3576  | 0  |         return(0);  | 
3577  | 0  |     switch (parent->type) { | 
3578  | 0  |         case XML_ELEMENT_NODE:  | 
3579  | 0  |         case XML_ENTITY_NODE:  | 
3580  | 0  |         case XML_DOCUMENT_NODE:  | 
3581  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
3582  | 0  |         case XML_HTML_DOCUMENT_NODE:  | 
3583  | 0  |             cur = parent->children;  | 
3584  | 0  |             break;  | 
3585  | 0  |         default:  | 
3586  | 0  |             return(0);  | 
3587  | 0  |     }  | 
3588  | 0  |     while (cur != NULL) { | 
3589  | 0  |         if (cur->type == XML_ELEMENT_NODE)  | 
3590  | 0  |             ret++;  | 
3591  | 0  |         cur = cur->next;  | 
3592  | 0  |     }  | 
3593  | 0  |     return(ret);  | 
3594  | 0  | }  | 
3595  |  |  | 
3596  |  | /**  | 
3597  |  |  * xmlFirstElementChild:  | 
3598  |  |  * @parent: the parent node  | 
3599  |  |  *  | 
3600  |  |  * Finds the first child node of that element which is a Element node  | 
3601  |  |  * Note the handling of entities references is different than in  | 
3602  |  |  * the W3C DOM element traversal spec since we don't have back reference  | 
3603  |  |  * from entities content to entities references.  | 
3604  |  |  *  | 
3605  |  |  * Returns the first element child or NULL if not available  | 
3606  |  |  */  | 
3607  |  | xmlNodePtr  | 
3608  | 0  | xmlFirstElementChild(xmlNodePtr parent) { | 
3609  | 0  |     xmlNodePtr cur = NULL;  | 
3610  |  | 
  | 
3611  | 0  |     if (parent == NULL)  | 
3612  | 0  |         return(NULL);  | 
3613  | 0  |     switch (parent->type) { | 
3614  | 0  |         case XML_ELEMENT_NODE:  | 
3615  | 0  |         case XML_ENTITY_NODE:  | 
3616  | 0  |         case XML_DOCUMENT_NODE:  | 
3617  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
3618  | 0  |         case XML_HTML_DOCUMENT_NODE:  | 
3619  | 0  |             cur = parent->children;  | 
3620  | 0  |             break;  | 
3621  | 0  |         default:  | 
3622  | 0  |             return(NULL);  | 
3623  | 0  |     }  | 
3624  | 0  |     while (cur != NULL) { | 
3625  | 0  |         if (cur->type == XML_ELEMENT_NODE)  | 
3626  | 0  |             return(cur);  | 
3627  | 0  |         cur = cur->next;  | 
3628  | 0  |     }  | 
3629  | 0  |     return(NULL);  | 
3630  | 0  | }  | 
3631  |  |  | 
3632  |  | /**  | 
3633  |  |  * xmlLastElementChild:  | 
3634  |  |  * @parent: the parent node  | 
3635  |  |  *  | 
3636  |  |  * Finds the last child node of that element which is a Element node  | 
3637  |  |  * Note the handling of entities references is different than in  | 
3638  |  |  * the W3C DOM element traversal spec since we don't have back reference  | 
3639  |  |  * from entities content to entities references.  | 
3640  |  |  *  | 
3641  |  |  * Returns the last element child or NULL if not available  | 
3642  |  |  */  | 
3643  |  | xmlNodePtr  | 
3644  | 0  | xmlLastElementChild(xmlNodePtr parent) { | 
3645  | 0  |     xmlNodePtr cur = NULL;  | 
3646  |  | 
  | 
3647  | 0  |     if (parent == NULL)  | 
3648  | 0  |         return(NULL);  | 
3649  | 0  |     switch (parent->type) { | 
3650  | 0  |         case XML_ELEMENT_NODE:  | 
3651  | 0  |         case XML_ENTITY_NODE:  | 
3652  | 0  |         case XML_DOCUMENT_NODE:  | 
3653  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
3654  | 0  |         case XML_HTML_DOCUMENT_NODE:  | 
3655  | 0  |             cur = parent->last;  | 
3656  | 0  |             break;  | 
3657  | 0  |         default:  | 
3658  | 0  |             return(NULL);  | 
3659  | 0  |     }  | 
3660  | 0  |     while (cur != NULL) { | 
3661  | 0  |         if (cur->type == XML_ELEMENT_NODE)  | 
3662  | 0  |             return(cur);  | 
3663  | 0  |         cur = cur->prev;  | 
3664  | 0  |     }  | 
3665  | 0  |     return(NULL);  | 
3666  | 0  | }  | 
3667  |  |  | 
3668  |  | /**  | 
3669  |  |  * xmlPreviousElementSibling:  | 
3670  |  |  * @node: the current node  | 
3671  |  |  *  | 
3672  |  |  * Finds the first closest previous sibling of the node which is an  | 
3673  |  |  * element node.  | 
3674  |  |  * Note the handling of entities references is different than in  | 
3675  |  |  * the W3C DOM element traversal spec since we don't have back reference  | 
3676  |  |  * from entities content to entities references.  | 
3677  |  |  *  | 
3678  |  |  * Returns the previous element sibling or NULL if not available  | 
3679  |  |  */  | 
3680  |  | xmlNodePtr  | 
3681  | 0  | xmlPreviousElementSibling(xmlNodePtr node) { | 
3682  | 0  |     if (node == NULL)  | 
3683  | 0  |         return(NULL);  | 
3684  | 0  |     switch (node->type) { | 
3685  | 0  |         case XML_ELEMENT_NODE:  | 
3686  | 0  |         case XML_TEXT_NODE:  | 
3687  | 0  |         case XML_CDATA_SECTION_NODE:  | 
3688  | 0  |         case XML_ENTITY_REF_NODE:  | 
3689  | 0  |         case XML_ENTITY_NODE:  | 
3690  | 0  |         case XML_PI_NODE:  | 
3691  | 0  |         case XML_COMMENT_NODE:  | 
3692  | 0  |         case XML_XINCLUDE_START:  | 
3693  | 0  |         case XML_XINCLUDE_END:  | 
3694  | 0  |             node = node->prev;  | 
3695  | 0  |             break;  | 
3696  | 0  |         default:  | 
3697  | 0  |             return(NULL);  | 
3698  | 0  |     }  | 
3699  | 0  |     while (node != NULL) { | 
3700  | 0  |         if (node->type == XML_ELEMENT_NODE)  | 
3701  | 0  |             return(node);  | 
3702  | 0  |         node = node->prev;  | 
3703  | 0  |     }  | 
3704  | 0  |     return(NULL);  | 
3705  | 0  | }  | 
3706  |  |  | 
3707  |  | /**  | 
3708  |  |  * xmlNextElementSibling:  | 
3709  |  |  * @node: the current node  | 
3710  |  |  *  | 
3711  |  |  * Finds the first closest next sibling of the node which is an  | 
3712  |  |  * element node.  | 
3713  |  |  * Note the handling of entities references is different than in  | 
3714  |  |  * the W3C DOM element traversal spec since we don't have back reference  | 
3715  |  |  * from entities content to entities references.  | 
3716  |  |  *  | 
3717  |  |  * Returns the next element sibling or NULL if not available  | 
3718  |  |  */  | 
3719  |  | xmlNodePtr  | 
3720  | 0  | xmlNextElementSibling(xmlNodePtr node) { | 
3721  | 0  |     if (node == NULL)  | 
3722  | 0  |         return(NULL);  | 
3723  | 0  |     switch (node->type) { | 
3724  | 0  |         case XML_ELEMENT_NODE:  | 
3725  | 0  |         case XML_TEXT_NODE:  | 
3726  | 0  |         case XML_CDATA_SECTION_NODE:  | 
3727  | 0  |         case XML_ENTITY_REF_NODE:  | 
3728  | 0  |         case XML_ENTITY_NODE:  | 
3729  | 0  |         case XML_PI_NODE:  | 
3730  | 0  |         case XML_COMMENT_NODE:  | 
3731  | 0  |         case XML_DTD_NODE:  | 
3732  | 0  |         case XML_XINCLUDE_START:  | 
3733  | 0  |         case XML_XINCLUDE_END:  | 
3734  | 0  |             node = node->next;  | 
3735  | 0  |             break;  | 
3736  | 0  |         default:  | 
3737  | 0  |             return(NULL);  | 
3738  | 0  |     }  | 
3739  | 0  |     while (node != NULL) { | 
3740  | 0  |         if (node->type == XML_ELEMENT_NODE)  | 
3741  | 0  |             return(node);  | 
3742  | 0  |         node = node->next;  | 
3743  | 0  |     }  | 
3744  | 0  |     return(NULL);  | 
3745  | 0  | }  | 
3746  |  |  | 
3747  |  | #endif /* LIBXML_TREE_ENABLED */  | 
3748  |  |  | 
3749  |  | /**  | 
3750  |  |  * xmlFreeNodeList:  | 
3751  |  |  * @cur:  the first node in the list  | 
3752  |  |  *  | 
3753  |  |  * Free a node and all its siblings, this is a recursive behaviour, all  | 
3754  |  |  * the children are freed too.  | 
3755  |  |  */  | 
3756  |  | void  | 
3757  | 194k  | xmlFreeNodeList(xmlNodePtr cur) { | 
3758  | 194k  |     xmlNodePtr next;  | 
3759  | 194k  |     xmlNodePtr parent;  | 
3760  | 194k  |     xmlDictPtr dict = NULL;  | 
3761  | 194k  |     size_t depth = 0;  | 
3762  |  |  | 
3763  | 194k  |     if (cur == NULL) return;  | 
3764  | 194k  |     if (cur->type == XML_NAMESPACE_DECL) { | 
3765  | 0  |   xmlFreeNsList((xmlNsPtr) cur);  | 
3766  | 0  |   return;  | 
3767  | 0  |     }  | 
3768  | 194k  |     if (cur->doc != NULL) dict = cur->doc->dict;  | 
3769  | 7.38M  |     while (1) { | 
3770  | 11.0M  |         while ((cur->children != NULL) &&  | 
3771  | 11.0M  |                (cur->type != XML_DOCUMENT_NODE) &&  | 
3772  | 11.0M  |                (cur->type != XML_HTML_DOCUMENT_NODE) &&  | 
3773  | 11.0M  |                (cur->type != XML_DTD_NODE) &&  | 
3774  | 11.0M  |                (cur->type != XML_ENTITY_REF_NODE)) { | 
3775  | 3.68M  |             cur = cur->children;  | 
3776  | 3.68M  |             depth += 1;  | 
3777  | 3.68M  |         }  | 
3778  |  |  | 
3779  | 7.38M  |         next = cur->next;  | 
3780  | 7.38M  |         parent = cur->parent;  | 
3781  | 7.38M  |   if ((cur->type == XML_DOCUMENT_NODE) ||  | 
3782  | 7.38M  |             (cur->type == XML_HTML_DOCUMENT_NODE)) { | 
3783  | 0  |             xmlFreeDoc((xmlDocPtr) cur);  | 
3784  | 7.38M  |         } else if (cur->type != XML_DTD_NODE) { | 
3785  |  |  | 
3786  | 7.38M  |       if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))  | 
3787  | 0  |     xmlDeregisterNodeDefaultValue(cur);  | 
3788  |  |  | 
3789  | 7.38M  |       if (((cur->type == XML_ELEMENT_NODE) ||  | 
3790  | 7.38M  |      (cur->type == XML_XINCLUDE_START) ||  | 
3791  | 7.38M  |      (cur->type == XML_XINCLUDE_END)) &&  | 
3792  | 7.38M  |     (cur->properties != NULL))  | 
3793  | 0  |     xmlFreePropList(cur->properties);  | 
3794  | 7.38M  |       if ((cur->type != XML_ELEMENT_NODE) &&  | 
3795  | 7.38M  |     (cur->type != XML_XINCLUDE_START) &&  | 
3796  | 7.38M  |     (cur->type != XML_XINCLUDE_END) &&  | 
3797  | 7.38M  |     (cur->type != XML_ENTITY_REF_NODE) &&  | 
3798  | 7.38M  |     (cur->content != (xmlChar *) &(cur->properties))) { | 
3799  | 3.69M  |     DICT_FREE(cur->content)  | 
3800  | 3.69M  |       }  | 
3801  | 7.38M  |       if (((cur->type == XML_ELEMENT_NODE) ||  | 
3802  | 7.38M  |            (cur->type == XML_XINCLUDE_START) ||  | 
3803  | 7.38M  |      (cur->type == XML_XINCLUDE_END)) &&  | 
3804  | 7.38M  |     (cur->nsDef != NULL))  | 
3805  | 413k  |     xmlFreeNsList(cur->nsDef);  | 
3806  |  |  | 
3807  |  |       /*  | 
3808  |  |        * When a node is a text node or a comment, it uses a global static  | 
3809  |  |        * variable for the name of the node.  | 
3810  |  |        * Otherwise the node name might come from the document's  | 
3811  |  |        * dictionary  | 
3812  |  |        */  | 
3813  | 7.38M  |       if ((cur->name != NULL) &&  | 
3814  | 7.38M  |     (cur->type != XML_TEXT_NODE) &&  | 
3815  | 7.38M  |     (cur->type != XML_COMMENT_NODE))  | 
3816  | 3.68M  |     DICT_FREE(cur->name)  | 
3817  | 7.38M  |       xmlFree(cur);  | 
3818  | 7.38M  |   }  | 
3819  |  |  | 
3820  | 7.38M  |         if (next != NULL) { | 
3821  | 3.50M  |       cur = next;  | 
3822  | 3.88M  |         } else { | 
3823  | 3.88M  |             if ((depth == 0) || (parent == NULL))  | 
3824  | 194k  |                 break;  | 
3825  | 3.68M  |             depth -= 1;  | 
3826  | 3.68M  |             cur = parent;  | 
3827  | 3.68M  |             cur->children = NULL;  | 
3828  | 3.68M  |         }  | 
3829  | 7.38M  |     }  | 
3830  | 194k  | }  | 
3831  |  |  | 
3832  |  | /**  | 
3833  |  |  * xmlFreeNode:  | 
3834  |  |  * @cur:  the node  | 
3835  |  |  *  | 
3836  |  |  * Free a node, this is a recursive behaviour, all the children are freed too.  | 
3837  |  |  * This doesn't unlink the child from the list, use xmlUnlinkNode() first.  | 
3838  |  |  */  | 
3839  |  | void  | 
3840  | 0  | xmlFreeNode(xmlNodePtr cur) { | 
3841  | 0  |     xmlDictPtr dict = NULL;  | 
3842  |  | 
  | 
3843  | 0  |     if (cur == NULL) return;  | 
3844  |  |  | 
3845  |  |     /* use xmlFreeDtd for DTD nodes */  | 
3846  | 0  |     if (cur->type == XML_DTD_NODE) { | 
3847  | 0  |   xmlFreeDtd((xmlDtdPtr) cur);  | 
3848  | 0  |   return;  | 
3849  | 0  |     }  | 
3850  | 0  |     if (cur->type == XML_NAMESPACE_DECL) { | 
3851  | 0  |   xmlFreeNs((xmlNsPtr) cur);  | 
3852  | 0  |         return;  | 
3853  | 0  |     }  | 
3854  | 0  |     if (cur->type == XML_ATTRIBUTE_NODE) { | 
3855  | 0  |   xmlFreeProp((xmlAttrPtr) cur);  | 
3856  | 0  |   return;  | 
3857  | 0  |     }  | 
3858  |  |  | 
3859  | 0  |     if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))  | 
3860  | 0  |   xmlDeregisterNodeDefaultValue(cur);  | 
3861  |  | 
  | 
3862  | 0  |     if (cur->doc != NULL) dict = cur->doc->dict;  | 
3863  |  | 
  | 
3864  | 0  |     if (cur->type == XML_ENTITY_DECL) { | 
3865  | 0  |         xmlEntityPtr ent = (xmlEntityPtr) cur;  | 
3866  | 0  |   DICT_FREE(ent->SystemID);  | 
3867  | 0  |   DICT_FREE(ent->ExternalID);  | 
3868  | 0  |     }  | 
3869  | 0  |     if ((cur->children != NULL) &&  | 
3870  | 0  |   (cur->type != XML_ENTITY_REF_NODE))  | 
3871  | 0  |   xmlFreeNodeList(cur->children);  | 
3872  |  | 
  | 
3873  | 0  |     if ((cur->type == XML_ELEMENT_NODE) ||  | 
3874  | 0  |         (cur->type == XML_XINCLUDE_START) ||  | 
3875  | 0  |         (cur->type == XML_XINCLUDE_END)) { | 
3876  | 0  |         if (cur->properties != NULL)  | 
3877  | 0  |             xmlFreePropList(cur->properties);  | 
3878  | 0  |         if (cur->nsDef != NULL)  | 
3879  | 0  |             xmlFreeNsList(cur->nsDef);  | 
3880  | 0  |     } else if ((cur->content != NULL) &&  | 
3881  | 0  |                (cur->type != XML_ENTITY_REF_NODE) &&  | 
3882  | 0  |                (cur->content != (xmlChar *) &(cur->properties))) { | 
3883  | 0  |         DICT_FREE(cur->content)  | 
3884  | 0  |     }  | 
3885  |  |  | 
3886  |  |     /*  | 
3887  |  |      * When a node is a text node or a comment, it uses a global static  | 
3888  |  |      * variable for the name of the node.  | 
3889  |  |      * Otherwise the node name might come from the document's dictionary  | 
3890  |  |      */  | 
3891  | 0  |     if ((cur->name != NULL) &&  | 
3892  | 0  |         (cur->type != XML_TEXT_NODE) &&  | 
3893  | 0  |         (cur->type != XML_COMMENT_NODE))  | 
3894  | 0  |   DICT_FREE(cur->name)  | 
3895  |  | 
  | 
3896  | 0  |     xmlFree(cur);  | 
3897  | 0  | }  | 
3898  |  |  | 
3899  |  | /**  | 
3900  |  |  * xmlUnlinkNode:  | 
3901  |  |  * @cur:  the node  | 
3902  |  |  *  | 
3903  |  |  * Unlink a node from it's current context, the node is not freed  | 
3904  |  |  * If one need to free the node, use xmlFreeNode() routine after the  | 
3905  |  |  * unlink to discard it.  | 
3906  |  |  * Note that namespace nodes can't be unlinked as they do not have  | 
3907  |  |  * pointer to their parent.  | 
3908  |  |  */  | 
3909  |  | void  | 
3910  | 0  | xmlUnlinkNode(xmlNodePtr cur) { | 
3911  | 0  |     if (cur == NULL) { | 
3912  |  | #ifdef DEBUG_TREE  | 
3913  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3914  |  |     "xmlUnlinkNode : node == NULL\n");  | 
3915  |  | #endif  | 
3916  | 0  |   return;  | 
3917  | 0  |     }  | 
3918  | 0  |     if (cur->type == XML_NAMESPACE_DECL)  | 
3919  | 0  |         return;  | 
3920  | 0  |     if (cur->type == XML_DTD_NODE) { | 
3921  | 0  |   xmlDocPtr doc;  | 
3922  | 0  |   doc = cur->doc;  | 
3923  | 0  |   if (doc != NULL) { | 
3924  | 0  |       if (doc->intSubset == (xmlDtdPtr) cur)  | 
3925  | 0  |     doc->intSubset = NULL;  | 
3926  | 0  |       if (doc->extSubset == (xmlDtdPtr) cur)  | 
3927  | 0  |     doc->extSubset = NULL;  | 
3928  | 0  |   }  | 
3929  | 0  |     }  | 
3930  | 0  |     if (cur->type == XML_ENTITY_DECL) { | 
3931  | 0  |         xmlDocPtr doc;  | 
3932  | 0  |   doc = cur->doc;  | 
3933  | 0  |   if (doc != NULL) { | 
3934  | 0  |       if (doc->intSubset != NULL) { | 
3935  | 0  |           if (xmlHashLookup(doc->intSubset->entities, cur->name) == cur)  | 
3936  | 0  |         xmlHashRemoveEntry(doc->intSubset->entities, cur->name,  | 
3937  | 0  |                            NULL);  | 
3938  | 0  |           if (xmlHashLookup(doc->intSubset->pentities, cur->name) == cur)  | 
3939  | 0  |         xmlHashRemoveEntry(doc->intSubset->pentities, cur->name,  | 
3940  | 0  |                            NULL);  | 
3941  | 0  |       }  | 
3942  | 0  |       if (doc->extSubset != NULL) { | 
3943  | 0  |           if (xmlHashLookup(doc->extSubset->entities, cur->name) == cur)  | 
3944  | 0  |         xmlHashRemoveEntry(doc->extSubset->entities, cur->name,  | 
3945  | 0  |                            NULL);  | 
3946  | 0  |           if (xmlHashLookup(doc->extSubset->pentities, cur->name) == cur)  | 
3947  | 0  |         xmlHashRemoveEntry(doc->extSubset->pentities, cur->name,  | 
3948  | 0  |                            NULL);  | 
3949  | 0  |       }  | 
3950  | 0  |   }  | 
3951  | 0  |     }  | 
3952  | 0  |     if (cur->parent != NULL) { | 
3953  | 0  |   xmlNodePtr parent;  | 
3954  | 0  |   parent = cur->parent;  | 
3955  | 0  |   if (cur->type == XML_ATTRIBUTE_NODE) { | 
3956  | 0  |       if (parent->properties == (xmlAttrPtr) cur)  | 
3957  | 0  |     parent->properties = ((xmlAttrPtr) cur)->next;  | 
3958  | 0  |   } else { | 
3959  | 0  |       if (parent->children == cur)  | 
3960  | 0  |     parent->children = cur->next;  | 
3961  | 0  |       if (parent->last == cur)  | 
3962  | 0  |     parent->last = cur->prev;  | 
3963  | 0  |   }  | 
3964  | 0  |   cur->parent = NULL;  | 
3965  | 0  |     }  | 
3966  | 0  |     if (cur->next != NULL)  | 
3967  | 0  |         cur->next->prev = cur->prev;  | 
3968  | 0  |     if (cur->prev != NULL)  | 
3969  | 0  |         cur->prev->next = cur->next;  | 
3970  | 0  |     cur->next = cur->prev = NULL;  | 
3971  | 0  | }  | 
3972  |  |  | 
3973  |  | #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)  | 
3974  |  | /**  | 
3975  |  |  * xmlReplaceNode:  | 
3976  |  |  * @old:  the old node  | 
3977  |  |  * @cur:  the node  | 
3978  |  |  *  | 
3979  |  |  * Unlink the old node from its current context, prune the new one  | 
3980  |  |  * at the same place. If @cur was already inserted in a document it is  | 
3981  |  |  * first unlinked from its existing context.  | 
3982  |  |  *  | 
3983  |  |  * See the note regarding namespaces in xmlAddChild.  | 
3984  |  |  *  | 
3985  |  |  * Returns the @old node  | 
3986  |  |  */  | 
3987  |  | xmlNodePtr  | 
3988  | 0  | xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) { | 
3989  | 0  |     if (old == cur) return(NULL);  | 
3990  | 0  |     if ((old == NULL) || (old->type == XML_NAMESPACE_DECL) ||  | 
3991  | 0  |         (old->parent == NULL)) { | 
3992  |  | #ifdef DEBUG_TREE  | 
3993  |  |         xmlGenericError(xmlGenericErrorContext,  | 
3994  |  |     "xmlReplaceNode : old == NULL or without parent\n");  | 
3995  |  | #endif  | 
3996  | 0  |   return(NULL);  | 
3997  | 0  |     }  | 
3998  | 0  |     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL)) { | 
3999  | 0  |   xmlUnlinkNode(old);  | 
4000  | 0  |   return(old);  | 
4001  | 0  |     }  | 
4002  | 0  |     if (cur == old) { | 
4003  | 0  |   return(old);  | 
4004  | 0  |     }  | 
4005  | 0  |     if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) { | 
4006  |  | #ifdef DEBUG_TREE  | 
4007  |  |         xmlGenericError(xmlGenericErrorContext,  | 
4008  |  |     "xmlReplaceNode : Trying to replace attribute node with other node type\n");  | 
4009  |  | #endif  | 
4010  | 0  |   return(old);  | 
4011  | 0  |     }  | 
4012  | 0  |     if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) { | 
4013  |  | #ifdef DEBUG_TREE  | 
4014  |  |         xmlGenericError(xmlGenericErrorContext,  | 
4015  |  |     "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n");  | 
4016  |  | #endif  | 
4017  | 0  |   return(old);  | 
4018  | 0  |     }  | 
4019  | 0  |     xmlUnlinkNode(cur);  | 
4020  | 0  |     xmlSetTreeDoc(cur, old->doc);  | 
4021  | 0  |     cur->parent = old->parent;  | 
4022  | 0  |     cur->next = old->next;  | 
4023  | 0  |     if (cur->next != NULL)  | 
4024  | 0  |   cur->next->prev = cur;  | 
4025  | 0  |     cur->prev = old->prev;  | 
4026  | 0  |     if (cur->prev != NULL)  | 
4027  | 0  |   cur->prev->next = cur;  | 
4028  | 0  |     if (cur->parent != NULL) { | 
4029  | 0  |   if (cur->type == XML_ATTRIBUTE_NODE) { | 
4030  | 0  |       if (cur->parent->properties == (xmlAttrPtr)old)  | 
4031  | 0  |     cur->parent->properties = ((xmlAttrPtr) cur);  | 
4032  | 0  |   } else { | 
4033  | 0  |       if (cur->parent->children == old)  | 
4034  | 0  |     cur->parent->children = cur;  | 
4035  | 0  |       if (cur->parent->last == old)  | 
4036  | 0  |     cur->parent->last = cur;  | 
4037  | 0  |   }  | 
4038  | 0  |     }  | 
4039  | 0  |     old->next = old->prev = NULL;  | 
4040  | 0  |     old->parent = NULL;  | 
4041  | 0  |     return(old);  | 
4042  | 0  | }  | 
4043  |  | #endif /* LIBXML_TREE_ENABLED */  | 
4044  |  |  | 
4045  |  | /************************************************************************  | 
4046  |  |  *                  *  | 
4047  |  |  *    Copy operations           *  | 
4048  |  |  *                  *  | 
4049  |  |  ************************************************************************/  | 
4050  |  |  | 
4051  |  | /**  | 
4052  |  |  * xmlCopyNamespace:  | 
4053  |  |  * @cur:  the namespace  | 
4054  |  |  *  | 
4055  |  |  * Do a copy of the namespace.  | 
4056  |  |  *  | 
4057  |  |  * Returns: a new #xmlNsPtr, or NULL in case of error.  | 
4058  |  |  */  | 
4059  |  | xmlNsPtr  | 
4060  | 0  | xmlCopyNamespace(xmlNsPtr cur) { | 
4061  | 0  |     xmlNsPtr ret;  | 
4062  |  | 
  | 
4063  | 0  |     if (cur == NULL) return(NULL);  | 
4064  | 0  |     switch (cur->type) { | 
4065  | 0  |   case XML_LOCAL_NAMESPACE:  | 
4066  | 0  |       ret = xmlNewNs(NULL, cur->href, cur->prefix);  | 
4067  | 0  |       break;  | 
4068  | 0  |   default:  | 
4069  |  | #ifdef DEBUG_TREE  | 
4070  |  |       xmlGenericError(xmlGenericErrorContext,  | 
4071  |  |         "xmlCopyNamespace: invalid type %d\n", cur->type);  | 
4072  |  | #endif  | 
4073  | 0  |       return(NULL);  | 
4074  | 0  |     }  | 
4075  | 0  |     return(ret);  | 
4076  | 0  | }  | 
4077  |  |  | 
4078  |  | /**  | 
4079  |  |  * xmlCopyNamespaceList:  | 
4080  |  |  * @cur:  the first namespace  | 
4081  |  |  *  | 
4082  |  |  * Do a copy of an namespace list.  | 
4083  |  |  *  | 
4084  |  |  * Returns: a new #xmlNsPtr, or NULL in case of error.  | 
4085  |  |  */  | 
4086  |  | xmlNsPtr  | 
4087  | 0  | xmlCopyNamespaceList(xmlNsPtr cur) { | 
4088  | 0  |     xmlNsPtr ret = NULL;  | 
4089  | 0  |     xmlNsPtr p = NULL,q;  | 
4090  |  | 
  | 
4091  | 0  |     while (cur != NULL) { | 
4092  | 0  |         q = xmlCopyNamespace(cur);  | 
4093  | 0  |   if (p == NULL) { | 
4094  | 0  |       ret = p = q;  | 
4095  | 0  |   } else { | 
4096  | 0  |       p->next = q;  | 
4097  | 0  |       p = q;  | 
4098  | 0  |   }  | 
4099  | 0  |   cur = cur->next;  | 
4100  | 0  |     }  | 
4101  | 0  |     return(ret);  | 
4102  | 0  | }  | 
4103  |  |  | 
4104  |  | static xmlAttrPtr  | 
4105  | 0  | xmlCopyPropInternal(xmlDocPtr doc, xmlNodePtr target, xmlAttrPtr cur) { | 
4106  | 0  |     xmlAttrPtr ret;  | 
4107  |  | 
  | 
4108  | 0  |     if (cur == NULL) return(NULL);  | 
4109  | 0  |     if ((target != NULL) && (target->type != XML_ELEMENT_NODE))  | 
4110  | 0  |         return(NULL);  | 
4111  | 0  |     if (target != NULL)  | 
4112  | 0  |   ret = xmlNewDocProp(target->doc, cur->name, NULL);  | 
4113  | 0  |     else if (doc != NULL)  | 
4114  | 0  |   ret = xmlNewDocProp(doc, cur->name, NULL);  | 
4115  | 0  |     else if (cur->parent != NULL)  | 
4116  | 0  |   ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL);  | 
4117  | 0  |     else if (cur->children != NULL)  | 
4118  | 0  |   ret = xmlNewDocProp(cur->children->doc, cur->name, NULL);  | 
4119  | 0  |     else  | 
4120  | 0  |   ret = xmlNewDocProp(NULL, cur->name, NULL);  | 
4121  | 0  |     if (ret == NULL) return(NULL);  | 
4122  | 0  |     ret->parent = target;  | 
4123  |  | 
  | 
4124  | 0  |     if ((cur->ns != NULL) && (target != NULL)) { | 
4125  | 0  |       xmlNsPtr ns;  | 
4126  |  | 
  | 
4127  | 0  |       ns = xmlSearchNs(target->doc, target, cur->ns->prefix);  | 
4128  | 0  |       if (ns == NULL) { | 
4129  |  |         /*  | 
4130  |  |          * Humm, we are copying an element whose namespace is defined  | 
4131  |  |          * out of the new tree scope. Search it in the original tree  | 
4132  |  |          * and add it at the top of the new tree  | 
4133  |  |          */  | 
4134  | 0  |         ns = xmlSearchNs(cur->doc, cur->parent, cur->ns->prefix);  | 
4135  | 0  |         if (ns != NULL) { | 
4136  | 0  |           xmlNodePtr root = target;  | 
4137  | 0  |           xmlNodePtr pred = NULL;  | 
4138  |  | 
  | 
4139  | 0  |           while (root->parent != NULL) { | 
4140  | 0  |             pred = root;  | 
4141  | 0  |             root = root->parent;  | 
4142  | 0  |           }  | 
4143  | 0  |           if (root == (xmlNodePtr) target->doc) { | 
4144  |  |             /* correct possibly cycling above the document elt */  | 
4145  | 0  |             root = pred;  | 
4146  | 0  |           }  | 
4147  | 0  |           ret->ns = xmlNewNs(root, ns->href, ns->prefix);  | 
4148  | 0  |         }  | 
4149  | 0  |       } else { | 
4150  |  |         /*  | 
4151  |  |          * we have to find something appropriate here since  | 
4152  |  |          * we can't be sure, that the namespace we found is identified  | 
4153  |  |          * by the prefix  | 
4154  |  |          */  | 
4155  | 0  |         if (xmlStrEqual(ns->href, cur->ns->href)) { | 
4156  |  |           /* this is the nice case */  | 
4157  | 0  |           ret->ns = ns;  | 
4158  | 0  |         } else { | 
4159  |  |           /*  | 
4160  |  |            * we are in trouble: we need a new reconciled namespace.  | 
4161  |  |            * This is expensive  | 
4162  |  |            */  | 
4163  | 0  |           ret->ns = xmlNewReconciledNs(target->doc, target, cur->ns);  | 
4164  | 0  |         }  | 
4165  | 0  |       }  | 
4166  |  | 
  | 
4167  | 0  |     } else  | 
4168  | 0  |         ret->ns = NULL;  | 
4169  |  | 
  | 
4170  | 0  |     if (cur->children != NULL) { | 
4171  | 0  |   xmlNodePtr tmp;  | 
4172  |  | 
  | 
4173  | 0  |   ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret);  | 
4174  | 0  |   ret->last = NULL;  | 
4175  | 0  |   tmp = ret->children;  | 
4176  | 0  |   while (tmp != NULL) { | 
4177  |  |       /* tmp->parent = (xmlNodePtr)ret; */  | 
4178  | 0  |       if (tmp->next == NULL)  | 
4179  | 0  |           ret->last = tmp;  | 
4180  | 0  |       tmp = tmp->next;  | 
4181  | 0  |   }  | 
4182  | 0  |     }  | 
4183  |  |     /*  | 
4184  |  |      * Try to handle IDs  | 
4185  |  |      */  | 
4186  | 0  |     if ((target!= NULL) && (cur!= NULL) &&  | 
4187  | 0  |   (target->doc != NULL) && (cur->doc != NULL) &&  | 
4188  | 0  |   (cur->doc->ids != NULL) && (cur->parent != NULL)) { | 
4189  | 0  |   if (xmlIsID(cur->doc, cur->parent, cur)) { | 
4190  | 0  |       xmlChar *id;  | 
4191  |  | 
  | 
4192  | 0  |       id = xmlNodeListGetString(cur->doc, cur->children, 1);  | 
4193  | 0  |       if (id != NULL) { | 
4194  | 0  |     xmlAddID(NULL, target->doc, id, ret);  | 
4195  | 0  |     xmlFree(id);  | 
4196  | 0  |       }  | 
4197  | 0  |   }  | 
4198  | 0  |     }  | 
4199  | 0  |     return(ret);  | 
4200  | 0  | }  | 
4201  |  |  | 
4202  |  | /**  | 
4203  |  |  * xmlCopyProp:  | 
4204  |  |  * @target:  the element where the attribute will be grafted  | 
4205  |  |  * @cur:  the attribute  | 
4206  |  |  *  | 
4207  |  |  * Do a copy of the attribute.  | 
4208  |  |  *  | 
4209  |  |  * Returns: a new #xmlAttrPtr, or NULL in case of error.  | 
4210  |  |  */  | 
4211  |  | xmlAttrPtr  | 
4212  | 0  | xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) { | 
4213  | 0  |   return xmlCopyPropInternal(NULL, target, cur);  | 
4214  | 0  | }  | 
4215  |  |  | 
4216  |  | /**  | 
4217  |  |  * xmlCopyPropList:  | 
4218  |  |  * @target:  the element where the attributes will be grafted  | 
4219  |  |  * @cur:  the first attribute  | 
4220  |  |  *  | 
4221  |  |  * Do a copy of an attribute list.  | 
4222  |  |  *  | 
4223  |  |  * Returns: a new #xmlAttrPtr, or NULL in case of error.  | 
4224  |  |  */  | 
4225  |  | xmlAttrPtr  | 
4226  | 0  | xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) { | 
4227  | 0  |     xmlAttrPtr ret = NULL;  | 
4228  | 0  |     xmlAttrPtr p = NULL,q;  | 
4229  |  | 
  | 
4230  | 0  |     if ((target != NULL) && (target->type != XML_ELEMENT_NODE))  | 
4231  | 0  |         return(NULL);  | 
4232  | 0  |     while (cur != NULL) { | 
4233  | 0  |         q = xmlCopyProp(target, cur);  | 
4234  | 0  |   if (q == NULL)  | 
4235  | 0  |       return(NULL);  | 
4236  | 0  |   if (p == NULL) { | 
4237  | 0  |       ret = p = q;  | 
4238  | 0  |   } else { | 
4239  | 0  |       p->next = q;  | 
4240  | 0  |       q->prev = p;  | 
4241  | 0  |       p = q;  | 
4242  | 0  |   }  | 
4243  | 0  |   cur = cur->next;  | 
4244  | 0  |     }  | 
4245  | 0  |     return(ret);  | 
4246  | 0  | }  | 
4247  |  |  | 
4248  |  | /*  | 
4249  |  |  * NOTE about the CopyNode operations !  | 
4250  |  |  *  | 
4251  |  |  * They are split into external and internal parts for one  | 
4252  |  |  * tricky reason: namespaces. Doing a direct copy of a node  | 
4253  |  |  * say RPM:Copyright without changing the namespace pointer to  | 
4254  |  |  * something else can produce stale links. One way to do it is  | 
4255  |  |  * to keep a reference counter but this doesn't work as soon  | 
4256  |  |  * as one moves the element or the subtree out of the scope of  | 
4257  |  |  * the existing namespace. The actual solution seems to be to add  | 
4258  |  |  * a copy of the namespace at the top of the copied tree if  | 
4259  |  |  * not available in the subtree.  | 
4260  |  |  * Hence two functions, the public front-end call the inner ones  | 
4261  |  |  * The argument "recursive" normally indicates a recursive copy  | 
4262  |  |  * of the node with values 0 (no) and 1 (yes).  For XInclude,  | 
4263  |  |  * however, we allow a value of 2 to indicate copy properties and  | 
4264  |  |  * namespace info, but don't recurse on children.  | 
4265  |  |  */  | 
4266  |  |  | 
4267  |  | xmlNodePtr  | 
4268  |  | xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,  | 
4269  | 0  |                   int extended) { | 
4270  | 0  |     xmlNodePtr ret;  | 
4271  |  | 
  | 
4272  | 0  |     if (node == NULL) return(NULL);  | 
4273  | 0  |     switch (node->type) { | 
4274  | 0  |         case XML_TEXT_NODE:  | 
4275  | 0  |         case XML_CDATA_SECTION_NODE:  | 
4276  | 0  |         case XML_ELEMENT_NODE:  | 
4277  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
4278  | 0  |         case XML_ENTITY_REF_NODE:  | 
4279  | 0  |         case XML_ENTITY_NODE:  | 
4280  | 0  |         case XML_PI_NODE:  | 
4281  | 0  |         case XML_COMMENT_NODE:  | 
4282  | 0  |         case XML_XINCLUDE_START:  | 
4283  | 0  |         case XML_XINCLUDE_END:  | 
4284  | 0  |       break;  | 
4285  | 0  |         case XML_ATTRIBUTE_NODE:  | 
4286  | 0  |     return((xmlNodePtr) xmlCopyPropInternal(doc, parent, (xmlAttrPtr) node));  | 
4287  | 0  |         case XML_NAMESPACE_DECL:  | 
4288  | 0  |       return((xmlNodePtr) xmlCopyNamespaceList((xmlNsPtr) node));  | 
4289  |  |  | 
4290  | 0  |         case XML_DOCUMENT_NODE:  | 
4291  | 0  |         case XML_HTML_DOCUMENT_NODE:  | 
4292  | 0  | #ifdef LIBXML_TREE_ENABLED  | 
4293  | 0  |       return((xmlNodePtr) xmlCopyDoc((xmlDocPtr) node, extended));  | 
4294  | 0  | #endif /* LIBXML_TREE_ENABLED */  | 
4295  | 0  |         case XML_DOCUMENT_TYPE_NODE:  | 
4296  | 0  |         case XML_NOTATION_NODE:  | 
4297  | 0  |         case XML_DTD_NODE:  | 
4298  | 0  |         case XML_ELEMENT_DECL:  | 
4299  | 0  |         case XML_ATTRIBUTE_DECL:  | 
4300  | 0  |         case XML_ENTITY_DECL:  | 
4301  | 0  |             return(NULL);  | 
4302  | 0  |     }  | 
4303  |  |  | 
4304  |  |     /*  | 
4305  |  |      * Allocate a new node and fill the fields.  | 
4306  |  |      */  | 
4307  | 0  |     ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));  | 
4308  | 0  |     if (ret == NULL) { | 
4309  | 0  |   xmlTreeErrMemory("copying node"); | 
4310  | 0  |   return(NULL);  | 
4311  | 0  |     }  | 
4312  | 0  |     memset(ret, 0, sizeof(xmlNode));  | 
4313  | 0  |     ret->type = node->type;  | 
4314  |  | 
  | 
4315  | 0  |     ret->doc = doc;  | 
4316  | 0  |     ret->parent = parent;  | 
4317  | 0  |     if (node->name == xmlStringText)  | 
4318  | 0  |   ret->name = xmlStringText;  | 
4319  | 0  |     else if (node->name == xmlStringTextNoenc)  | 
4320  | 0  |   ret->name = xmlStringTextNoenc;  | 
4321  | 0  |     else if (node->name == xmlStringComment)  | 
4322  | 0  |   ret->name = xmlStringComment;  | 
4323  | 0  |     else if (node->name != NULL) { | 
4324  | 0  |         if ((doc != NULL) && (doc->dict != NULL))  | 
4325  | 0  |       ret->name = xmlDictLookup(doc->dict, node->name, -1);  | 
4326  | 0  |   else  | 
4327  | 0  |       ret->name = xmlStrdup(node->name);  | 
4328  | 0  |     }  | 
4329  | 0  |     if ((node->type != XML_ELEMENT_NODE) &&  | 
4330  | 0  |   (node->content != NULL) &&  | 
4331  | 0  |   (node->type != XML_ENTITY_REF_NODE) &&  | 
4332  | 0  |   (node->type != XML_XINCLUDE_END) &&  | 
4333  | 0  |   (node->type != XML_XINCLUDE_START)) { | 
4334  | 0  |   ret->content = xmlStrdup(node->content);  | 
4335  | 0  |     }else{ | 
4336  | 0  |       if (node->type == XML_ELEMENT_NODE)  | 
4337  | 0  |         ret->line = node->line;  | 
4338  | 0  |     }  | 
4339  | 0  |     if (parent != NULL) { | 
4340  | 0  |   xmlNodePtr tmp;  | 
4341  |  |  | 
4342  |  |   /*  | 
4343  |  |    * this is a tricky part for the node register thing:  | 
4344  |  |    * in case ret does get coalesced in xmlAddChild  | 
4345  |  |    * the deregister-node callback is called; so we register ret now already  | 
4346  |  |    */  | 
4347  | 0  |   if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))  | 
4348  | 0  |       xmlRegisterNodeDefaultValue((xmlNodePtr)ret);  | 
4349  |  |  | 
4350  |  |         /*  | 
4351  |  |          * Note that since ret->parent is already set, xmlAddChild will  | 
4352  |  |          * return early and not actually insert the node. It will only  | 
4353  |  |          * coalesce text nodes and unnecessarily call xmlSetTreeDoc.  | 
4354  |  |          * Assuming that the subtree to be copied always has its text  | 
4355  |  |          * nodes coalesced, the somewhat confusing call to xmlAddChild  | 
4356  |  |          * could be removed.  | 
4357  |  |          */  | 
4358  | 0  |         tmp = xmlAddChild(parent, ret);  | 
4359  |  |   /* node could have coalesced */  | 
4360  | 0  |   if (tmp != ret)  | 
4361  | 0  |       return(tmp);  | 
4362  | 0  |     }  | 
4363  |  |  | 
4364  | 0  |     if (!extended)  | 
4365  | 0  |   goto out;  | 
4366  | 0  |     if (((node->type == XML_ELEMENT_NODE) ||  | 
4367  | 0  |          (node->type == XML_XINCLUDE_START)) && (node->nsDef != NULL))  | 
4368  | 0  |         ret->nsDef = xmlCopyNamespaceList(node->nsDef);  | 
4369  |  | 
  | 
4370  | 0  |     if (node->ns != NULL) { | 
4371  | 0  |         xmlNsPtr ns;  | 
4372  |  | 
  | 
4373  | 0  |   ns = xmlSearchNs(doc, ret, node->ns->prefix);  | 
4374  | 0  |   if (ns == NULL) { | 
4375  |  |       /*  | 
4376  |  |        * Humm, we are copying an element whose namespace is defined  | 
4377  |  |        * out of the new tree scope. Search it in the original tree  | 
4378  |  |        * and add it at the top of the new tree  | 
4379  |  |        */  | 
4380  | 0  |       ns = xmlSearchNs(node->doc, node, node->ns->prefix);  | 
4381  | 0  |       if (ns != NULL) { | 
4382  | 0  |           xmlNodePtr root = ret;  | 
4383  |  | 
  | 
4384  | 0  |     while (root->parent != NULL) root = root->parent;  | 
4385  | 0  |     ret->ns = xmlNewNs(root, ns->href, ns->prefix);  | 
4386  | 0  |     } else { | 
4387  | 0  |       ret->ns = xmlNewReconciledNs(doc, ret, node->ns);  | 
4388  | 0  |       }  | 
4389  | 0  |   } else { | 
4390  |  |       /*  | 
4391  |  |        * reference the existing namespace definition in our own tree.  | 
4392  |  |        */  | 
4393  | 0  |       ret->ns = ns;  | 
4394  | 0  |   }  | 
4395  | 0  |     }  | 
4396  | 0  |     if (((node->type == XML_ELEMENT_NODE) ||  | 
4397  | 0  |          (node->type == XML_XINCLUDE_START)) && (node->properties != NULL))  | 
4398  | 0  |         ret->properties = xmlCopyPropList(ret, node->properties);  | 
4399  | 0  |     if (node->type == XML_ENTITY_REF_NODE) { | 
4400  | 0  |   if ((doc == NULL) || (node->doc != doc)) { | 
4401  |  |       /*  | 
4402  |  |        * The copied node will go into a separate document, so  | 
4403  |  |        * to avoid dangling references to the ENTITY_DECL node  | 
4404  |  |        * we cannot keep the reference. Try to find it in the  | 
4405  |  |        * target document.  | 
4406  |  |        */  | 
4407  | 0  |       ret->children = (xmlNodePtr) xmlGetDocEntity(doc, ret->name);  | 
4408  | 0  |   } else { | 
4409  | 0  |             ret->children = node->children;  | 
4410  | 0  |   }  | 
4411  | 0  |   ret->last = ret->children;  | 
4412  | 0  |     } else if ((node->children != NULL) && (extended != 2)) { | 
4413  | 0  |         xmlNodePtr cur, insert;  | 
4414  |  | 
  | 
4415  | 0  |         cur = node->children;  | 
4416  | 0  |         insert = ret;  | 
4417  | 0  |         while (cur != NULL) { | 
4418  | 0  |             xmlNodePtr copy = xmlStaticCopyNode(cur, doc, insert, 2);  | 
4419  | 0  |             if (copy == NULL) { | 
4420  | 0  |                 xmlFreeNode(ret);  | 
4421  | 0  |                 return(NULL);  | 
4422  | 0  |             }  | 
4423  |  |  | 
4424  |  |             /* Check for coalesced text nodes */  | 
4425  | 0  |             if (insert->last != copy) { | 
4426  | 0  |                 if (insert->last == NULL) { | 
4427  | 0  |                     insert->children = copy;  | 
4428  | 0  |                 } else { | 
4429  | 0  |                     copy->prev = insert->last;  | 
4430  | 0  |                     insert->last->next = copy;  | 
4431  | 0  |                 }  | 
4432  | 0  |                 insert->last = copy;  | 
4433  | 0  |             }  | 
4434  |  | 
  | 
4435  | 0  |             if ((cur->type != XML_ENTITY_REF_NODE) &&  | 
4436  | 0  |                 (cur->children != NULL)) { | 
4437  | 0  |                 cur = cur->children;  | 
4438  | 0  |                 insert = copy;  | 
4439  | 0  |                 continue;  | 
4440  | 0  |             }  | 
4441  |  |  | 
4442  | 0  |             while (1) { | 
4443  | 0  |                 if (cur->next != NULL) { | 
4444  | 0  |                     cur = cur->next;  | 
4445  | 0  |                     break;  | 
4446  | 0  |                 }  | 
4447  |  |  | 
4448  | 0  |                 cur = cur->parent;  | 
4449  | 0  |                 insert = insert->parent;  | 
4450  | 0  |                 if (cur == node) { | 
4451  | 0  |                     cur = NULL;  | 
4452  | 0  |                     break;  | 
4453  | 0  |                 }  | 
4454  | 0  |             }  | 
4455  | 0  |         }  | 
4456  | 0  |     }  | 
4457  |  |  | 
4458  | 0  | out:  | 
4459  |  |     /* if parent != NULL we already registered the node above */  | 
4460  | 0  |     if ((parent == NULL) &&  | 
4461  | 0  |         ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue)))  | 
4462  | 0  |   xmlRegisterNodeDefaultValue((xmlNodePtr)ret);  | 
4463  | 0  |     return(ret);  | 
4464  | 0  | }  | 
4465  |  |  | 
4466  |  | xmlNodePtr  | 
4467  | 0  | xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { | 
4468  | 0  |     xmlNodePtr ret = NULL;  | 
4469  | 0  |     xmlNodePtr p = NULL,q;  | 
4470  |  | 
  | 
4471  | 0  |     while (node != NULL) { | 
4472  | 0  | #ifdef LIBXML_TREE_ENABLED  | 
4473  | 0  |   if (node->type == XML_DTD_NODE ) { | 
4474  | 0  |       if (doc == NULL) { | 
4475  | 0  |     node = node->next;  | 
4476  | 0  |     continue;  | 
4477  | 0  |       }  | 
4478  | 0  |       if (doc->intSubset == NULL) { | 
4479  | 0  |     q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node );  | 
4480  | 0  |     if (q == NULL) goto error;  | 
4481  | 0  |     q->doc = doc;  | 
4482  | 0  |     q->parent = parent;  | 
4483  | 0  |     doc->intSubset = (xmlDtdPtr) q;  | 
4484  | 0  |     xmlAddChild(parent, q);  | 
4485  | 0  |       } else { | 
4486  | 0  |     q = (xmlNodePtr) doc->intSubset;  | 
4487  | 0  |     xmlAddChild(parent, q);  | 
4488  | 0  |       }  | 
4489  | 0  |   } else  | 
4490  | 0  | #endif /* LIBXML_TREE_ENABLED */  | 
4491  | 0  |       q = xmlStaticCopyNode(node, doc, parent, 1);  | 
4492  | 0  |   if (q == NULL) goto error;  | 
4493  | 0  |   if (ret == NULL) { | 
4494  | 0  |       q->prev = NULL;  | 
4495  | 0  |       ret = p = q;  | 
4496  | 0  |   } else if (p != q) { | 
4497  |  |   /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */  | 
4498  | 0  |       p->next = q;  | 
4499  | 0  |       q->prev = p;  | 
4500  | 0  |       p = q;  | 
4501  | 0  |   }  | 
4502  | 0  |   node = node->next;  | 
4503  | 0  |     }  | 
4504  | 0  |     return(ret);  | 
4505  | 0  | error:  | 
4506  | 0  |     xmlFreeNodeList(ret);  | 
4507  | 0  |     return(NULL);  | 
4508  | 0  | }  | 
4509  |  |  | 
4510  |  | /**  | 
4511  |  |  * xmlCopyNode:  | 
4512  |  |  * @node:  the node  | 
4513  |  |  * @extended:   if 1 do a recursive copy (properties, namespaces and children  | 
4514  |  |  *      when applicable)  | 
4515  |  |  *    if 2 copy properties and namespaces (when applicable)  | 
4516  |  |  *  | 
4517  |  |  * Do a copy of the node.  | 
4518  |  |  *  | 
4519  |  |  * Returns: a new #xmlNodePtr, or NULL in case of error.  | 
4520  |  |  */  | 
4521  |  | xmlNodePtr  | 
4522  | 0  | xmlCopyNode(xmlNodePtr node, int extended) { | 
4523  | 0  |     xmlNodePtr ret;  | 
4524  |  | 
  | 
4525  | 0  |     ret = xmlStaticCopyNode(node, NULL, NULL, extended);  | 
4526  | 0  |     return(ret);  | 
4527  | 0  | }  | 
4528  |  |  | 
4529  |  | /**  | 
4530  |  |  * xmlDocCopyNode:  | 
4531  |  |  * @node:  the node  | 
4532  |  |  * @doc:  the document  | 
4533  |  |  * @extended:   if 1 do a recursive copy (properties, namespaces and children  | 
4534  |  |  *      when applicable)  | 
4535  |  |  *    if 2 copy properties and namespaces (when applicable)  | 
4536  |  |  *  | 
4537  |  |  * Do a copy of the node to a given document.  | 
4538  |  |  *  | 
4539  |  |  * Returns: a new #xmlNodePtr, or NULL in case of error.  | 
4540  |  |  */  | 
4541  |  | xmlNodePtr  | 
4542  | 0  | xmlDocCopyNode(xmlNodePtr node, xmlDocPtr doc, int extended) { | 
4543  | 0  |     xmlNodePtr ret;  | 
4544  |  | 
  | 
4545  | 0  |     ret = xmlStaticCopyNode(node, doc, NULL, extended);  | 
4546  | 0  |     return(ret);  | 
4547  | 0  | }  | 
4548  |  |  | 
4549  |  | /**  | 
4550  |  |  * xmlDocCopyNodeList:  | 
4551  |  |  * @doc: the target document  | 
4552  |  |  * @node:  the first node in the list.  | 
4553  |  |  *  | 
4554  |  |  * Do a recursive copy of the node list.  | 
4555  |  |  *  | 
4556  |  |  * Returns: a new #xmlNodePtr, or NULL in case of error.  | 
4557  |  |  */  | 
4558  | 0  | xmlNodePtr xmlDocCopyNodeList(xmlDocPtr doc, xmlNodePtr node) { | 
4559  | 0  |     xmlNodePtr ret = xmlStaticCopyNodeList(node, doc, NULL);  | 
4560  | 0  |     return(ret);  | 
4561  | 0  | }  | 
4562  |  |  | 
4563  |  | /**  | 
4564  |  |  * xmlCopyNodeList:  | 
4565  |  |  * @node:  the first node in the list.  | 
4566  |  |  *  | 
4567  |  |  * Do a recursive copy of the node list.  | 
4568  |  |  * Use xmlDocCopyNodeList() if possible to ensure string interning.  | 
4569  |  |  *  | 
4570  |  |  * Returns: a new #xmlNodePtr, or NULL in case of error.  | 
4571  |  |  */  | 
4572  | 0  | xmlNodePtr xmlCopyNodeList(xmlNodePtr node) { | 
4573  | 0  |     xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);  | 
4574  | 0  |     return(ret);  | 
4575  | 0  | }  | 
4576  |  |  | 
4577  |  | #if defined(LIBXML_TREE_ENABLED)  | 
4578  |  | /**  | 
4579  |  |  * xmlCopyDtd:  | 
4580  |  |  * @dtd:  the dtd  | 
4581  |  |  *  | 
4582  |  |  * Do a copy of the dtd.  | 
4583  |  |  *  | 
4584  |  |  * Returns: a new #xmlDtdPtr, or NULL in case of error.  | 
4585  |  |  */  | 
4586  |  | xmlDtdPtr  | 
4587  | 0  | xmlCopyDtd(xmlDtdPtr dtd) { | 
4588  | 0  |     xmlDtdPtr ret;  | 
4589  | 0  |     xmlNodePtr cur, p = NULL, q;  | 
4590  |  | 
  | 
4591  | 0  |     if (dtd == NULL) return(NULL);  | 
4592  | 0  |     ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);  | 
4593  | 0  |     if (ret == NULL) return(NULL);  | 
4594  | 0  |     if (dtd->entities != NULL)  | 
4595  | 0  |         ret->entities = (void *) xmlCopyEntitiesTable(  | 
4596  | 0  |                       (xmlEntitiesTablePtr) dtd->entities);  | 
4597  | 0  |     if (dtd->notations != NULL)  | 
4598  | 0  |         ret->notations = (void *) xmlCopyNotationTable(  | 
4599  | 0  |                       (xmlNotationTablePtr) dtd->notations);  | 
4600  | 0  |     if (dtd->elements != NULL)  | 
4601  | 0  |         ret->elements = (void *) xmlCopyElementTable(  | 
4602  | 0  |                       (xmlElementTablePtr) dtd->elements);  | 
4603  | 0  |     if (dtd->attributes != NULL)  | 
4604  | 0  |         ret->attributes = (void *) xmlCopyAttributeTable(  | 
4605  | 0  |                       (xmlAttributeTablePtr) dtd->attributes);  | 
4606  | 0  |     if (dtd->pentities != NULL)  | 
4607  | 0  |   ret->pentities = (void *) xmlCopyEntitiesTable(  | 
4608  | 0  |           (xmlEntitiesTablePtr) dtd->pentities);  | 
4609  |  | 
  | 
4610  | 0  |     cur = dtd->children;  | 
4611  | 0  |     while (cur != NULL) { | 
4612  | 0  |   q = NULL;  | 
4613  |  | 
  | 
4614  | 0  |   if (cur->type == XML_ENTITY_DECL) { | 
4615  | 0  |       xmlEntityPtr tmp = (xmlEntityPtr) cur;  | 
4616  | 0  |       switch (tmp->etype) { | 
4617  | 0  |     case XML_INTERNAL_GENERAL_ENTITY:  | 
4618  | 0  |     case XML_EXTERNAL_GENERAL_PARSED_ENTITY:  | 
4619  | 0  |     case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:  | 
4620  | 0  |         q = (xmlNodePtr) xmlGetEntityFromDtd(ret, tmp->name);  | 
4621  | 0  |         break;  | 
4622  | 0  |     case XML_INTERNAL_PARAMETER_ENTITY:  | 
4623  | 0  |     case XML_EXTERNAL_PARAMETER_ENTITY:  | 
4624  | 0  |         q = (xmlNodePtr)  | 
4625  | 0  |       xmlGetParameterEntityFromDtd(ret, tmp->name);  | 
4626  | 0  |         break;  | 
4627  | 0  |     case XML_INTERNAL_PREDEFINED_ENTITY:  | 
4628  | 0  |         break;  | 
4629  | 0  |       }  | 
4630  | 0  |   } else if (cur->type == XML_ELEMENT_DECL) { | 
4631  | 0  |       xmlElementPtr tmp = (xmlElementPtr) cur;  | 
4632  | 0  |       q = (xmlNodePtr)  | 
4633  | 0  |     xmlGetDtdQElementDesc(ret, tmp->name, tmp->prefix);  | 
4634  | 0  |   } else if (cur->type == XML_ATTRIBUTE_DECL) { | 
4635  | 0  |       xmlAttributePtr tmp = (xmlAttributePtr) cur;  | 
4636  | 0  |       q = (xmlNodePtr)  | 
4637  | 0  |     xmlGetDtdQAttrDesc(ret, tmp->elem, tmp->name, tmp->prefix);  | 
4638  | 0  |   } else if (cur->type == XML_COMMENT_NODE) { | 
4639  | 0  |       q = xmlCopyNode(cur, 0);  | 
4640  | 0  |   }  | 
4641  |  |  | 
4642  | 0  |   if (q == NULL) { | 
4643  | 0  |       cur = cur->next;  | 
4644  | 0  |       continue;  | 
4645  | 0  |   }  | 
4646  |  |  | 
4647  | 0  |   if (p == NULL)  | 
4648  | 0  |       ret->children = q;  | 
4649  | 0  |   else  | 
4650  | 0  |       p->next = q;  | 
4651  |  | 
  | 
4652  | 0  |   q->prev = p;  | 
4653  | 0  |   q->parent = (xmlNodePtr) ret;  | 
4654  | 0  |   q->next = NULL;  | 
4655  | 0  |   ret->last = q;  | 
4656  | 0  |   p = q;  | 
4657  | 0  |   cur = cur->next;  | 
4658  | 0  |     }  | 
4659  |  |  | 
4660  | 0  |     return(ret);  | 
4661  | 0  | }  | 
4662  |  | #endif  | 
4663  |  |  | 
4664  |  | #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)  | 
4665  |  | /**  | 
4666  |  |  * xmlCopyDoc:  | 
4667  |  |  * @doc:  the document  | 
4668  |  |  * @recursive:  if not zero do a recursive copy.  | 
4669  |  |  *  | 
4670  |  |  * Do a copy of the document info. If recursive, the content tree will  | 
4671  |  |  * be copied too as well as DTD, namespaces and entities.  | 
4672  |  |  *  | 
4673  |  |  * Returns: a new #xmlDocPtr, or NULL in case of error.  | 
4674  |  |  */  | 
4675  |  | xmlDocPtr  | 
4676  | 0  | xmlCopyDoc(xmlDocPtr doc, int recursive) { | 
4677  | 0  |     xmlDocPtr ret;  | 
4678  |  | 
  | 
4679  | 0  |     if (doc == NULL) return(NULL);  | 
4680  | 0  |     ret = xmlNewDoc(doc->version);  | 
4681  | 0  |     if (ret == NULL) return(NULL);  | 
4682  | 0  |     ret->type = doc->type;  | 
4683  | 0  |     if (doc->name != NULL)  | 
4684  | 0  |         ret->name = xmlMemStrdup(doc->name);  | 
4685  | 0  |     if (doc->encoding != NULL)  | 
4686  | 0  |         ret->encoding = xmlStrdup(doc->encoding);  | 
4687  | 0  |     if (doc->URL != NULL)  | 
4688  | 0  |         ret->URL = xmlStrdup(doc->URL);  | 
4689  | 0  |     ret->charset = doc->charset;  | 
4690  | 0  |     ret->compression = doc->compression;  | 
4691  | 0  |     ret->standalone = doc->standalone;  | 
4692  | 0  |     if (!recursive) return(ret);  | 
4693  |  |  | 
4694  | 0  |     ret->last = NULL;  | 
4695  | 0  |     ret->children = NULL;  | 
4696  | 0  | #ifdef LIBXML_TREE_ENABLED  | 
4697  | 0  |     if (doc->intSubset != NULL) { | 
4698  | 0  |         ret->intSubset = xmlCopyDtd(doc->intSubset);  | 
4699  | 0  |   if (ret->intSubset == NULL) { | 
4700  | 0  |       xmlFreeDoc(ret);  | 
4701  | 0  |       return(NULL);  | 
4702  | 0  |   }  | 
4703  | 0  |   xmlSetTreeDoc((xmlNodePtr)ret->intSubset, ret);  | 
4704  | 0  |   ret->intSubset->parent = ret;  | 
4705  | 0  |     }  | 
4706  | 0  | #endif  | 
4707  | 0  |     if (doc->oldNs != NULL)  | 
4708  | 0  |         ret->oldNs = xmlCopyNamespaceList(doc->oldNs);  | 
4709  | 0  |     if (doc->children != NULL) { | 
4710  | 0  |   xmlNodePtr tmp;  | 
4711  |  | 
  | 
4712  | 0  |   ret->children = xmlStaticCopyNodeList(doc->children, ret,  | 
4713  | 0  |                                    (xmlNodePtr)ret);  | 
4714  | 0  |   ret->last = NULL;  | 
4715  | 0  |   tmp = ret->children;  | 
4716  | 0  |   while (tmp != NULL) { | 
4717  | 0  |       if (tmp->next == NULL)  | 
4718  | 0  |           ret->last = tmp;  | 
4719  | 0  |       tmp = tmp->next;  | 
4720  | 0  |   }  | 
4721  | 0  |     }  | 
4722  | 0  |     return(ret);  | 
4723  | 0  | }  | 
4724  |  | #endif /* LIBXML_TREE_ENABLED */  | 
4725  |  |  | 
4726  |  | /************************************************************************  | 
4727  |  |  *                  *  | 
4728  |  |  *    Content access functions        *  | 
4729  |  |  *                  *  | 
4730  |  |  ************************************************************************/  | 
4731  |  |  | 
4732  |  | /**  | 
4733  |  |  * xmlGetLineNoInternal:  | 
4734  |  |  * @node: valid node  | 
4735  |  |  * @depth: used to limit any risk of recursion  | 
4736  |  |  *  | 
4737  |  |  * Get line number of @node.  | 
4738  |  |  * Try to override the limitation of lines being store in 16 bits ints  | 
4739  |  |  *  | 
4740  |  |  * Returns the line number if successful, -1 otherwise  | 
4741  |  |  */  | 
4742  |  | static long  | 
4743  |  | xmlGetLineNoInternal(const xmlNode *node, int depth)  | 
4744  | 3.63M  | { | 
4745  | 3.63M  |     long result = -1;  | 
4746  |  |  | 
4747  | 3.63M  |     if (depth >= 5)  | 
4748  | 0  |         return(-1);  | 
4749  |  |  | 
4750  | 3.63M  |     if (!node)  | 
4751  | 0  |         return result;  | 
4752  | 3.63M  |     if ((node->type == XML_ELEMENT_NODE) ||  | 
4753  | 3.63M  |         (node->type == XML_TEXT_NODE) ||  | 
4754  | 3.63M  |   (node->type == XML_COMMENT_NODE) ||  | 
4755  | 3.63M  |   (node->type == XML_PI_NODE)) { | 
4756  | 3.63M  |   if (node->line == 65535) { | 
4757  | 0  |       if ((node->type == XML_TEXT_NODE) && (node->psvi != NULL))  | 
4758  | 0  |           result = (long) (ptrdiff_t) node->psvi;  | 
4759  | 0  |       else if ((node->type == XML_ELEMENT_NODE) &&  | 
4760  | 0  |                (node->children != NULL))  | 
4761  | 0  |           result = xmlGetLineNoInternal(node->children, depth + 1);  | 
4762  | 0  |       else if (node->next != NULL)  | 
4763  | 0  |           result = xmlGetLineNoInternal(node->next, depth + 1);  | 
4764  | 0  |       else if (node->prev != NULL)  | 
4765  | 0  |           result = xmlGetLineNoInternal(node->prev, depth + 1);  | 
4766  | 0  |   }  | 
4767  | 3.63M  |   if ((result == -1) || (result == 65535))  | 
4768  | 3.63M  |       result = (long) node->line;  | 
4769  | 3.63M  |     } else if ((node->prev != NULL) &&  | 
4770  | 455  |              ((node->prev->type == XML_ELEMENT_NODE) ||  | 
4771  | 3  |         (node->prev->type == XML_TEXT_NODE) ||  | 
4772  | 3  |         (node->prev->type == XML_COMMENT_NODE) ||  | 
4773  | 3  |         (node->prev->type == XML_PI_NODE)))  | 
4774  | 0  |         result = xmlGetLineNoInternal(node->prev, depth + 1);  | 
4775  | 455  |     else if ((node->parent != NULL) &&  | 
4776  | 455  |              (node->parent->type == XML_ELEMENT_NODE))  | 
4777  | 180  |         result = xmlGetLineNoInternal(node->parent, depth + 1);  | 
4778  |  |  | 
4779  | 3.63M  |     return result;  | 
4780  | 3.63M  | }  | 
4781  |  |  | 
4782  |  | /**  | 
4783  |  |  * xmlGetLineNo:  | 
4784  |  |  * @node: valid node  | 
4785  |  |  *  | 
4786  |  |  * Get line number of @node.  | 
4787  |  |  * Try to override the limitation of lines being store in 16 bits ints  | 
4788  |  |  * if XML_PARSE_BIG_LINES parser option was used  | 
4789  |  |  *  | 
4790  |  |  * Returns the line number if successful, -1 otherwise  | 
4791  |  |  */  | 
4792  |  | long  | 
4793  |  | xmlGetLineNo(const xmlNode *node)  | 
4794  | 3.63M  | { | 
4795  | 3.63M  |     return(xmlGetLineNoInternal(node, 0));  | 
4796  | 3.63M  | }  | 
4797  |  |  | 
4798  |  | #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)  | 
4799  |  | /**  | 
4800  |  |  * xmlGetNodePath:  | 
4801  |  |  * @node: a node  | 
4802  |  |  *  | 
4803  |  |  * Build a structure based Path for the given node  | 
4804  |  |  *  | 
4805  |  |  * Returns the new path or NULL in case of error. The caller must free  | 
4806  |  |  *     the returned string  | 
4807  |  |  */  | 
4808  |  | xmlChar *  | 
4809  |  | xmlGetNodePath(const xmlNode *node)  | 
4810  | 0  | { | 
4811  | 0  |     const xmlNode *cur, *tmp, *next;  | 
4812  | 0  |     xmlChar *buffer = NULL, *temp;  | 
4813  | 0  |     size_t buf_len;  | 
4814  | 0  |     xmlChar *buf;  | 
4815  | 0  |     const char *sep;  | 
4816  | 0  |     const char *name;  | 
4817  | 0  |     char nametemp[100];  | 
4818  | 0  |     int occur = 0, generic;  | 
4819  |  | 
  | 
4820  | 0  |     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))  | 
4821  | 0  |         return (NULL);  | 
4822  |  |  | 
4823  | 0  |     buf_len = 500;  | 
4824  | 0  |     buffer = (xmlChar *) xmlMallocAtomic(buf_len);  | 
4825  | 0  |     if (buffer == NULL) { | 
4826  | 0  |   xmlTreeErrMemory("getting node path"); | 
4827  | 0  |         return (NULL);  | 
4828  | 0  |     }  | 
4829  | 0  |     buf = (xmlChar *) xmlMallocAtomic(buf_len);  | 
4830  | 0  |     if (buf == NULL) { | 
4831  | 0  |   xmlTreeErrMemory("getting node path"); | 
4832  | 0  |         xmlFree(buffer);  | 
4833  | 0  |         return (NULL);  | 
4834  | 0  |     }  | 
4835  |  |  | 
4836  | 0  |     buffer[0] = 0;  | 
4837  | 0  |     cur = node;  | 
4838  | 0  |     do { | 
4839  | 0  |         name = "";  | 
4840  | 0  |         sep = "?";  | 
4841  | 0  |         occur = 0;  | 
4842  | 0  |         if ((cur->type == XML_DOCUMENT_NODE) ||  | 
4843  | 0  |             (cur->type == XML_HTML_DOCUMENT_NODE)) { | 
4844  | 0  |             if (buffer[0] == '/')  | 
4845  | 0  |                 break;  | 
4846  | 0  |             sep = "/";  | 
4847  | 0  |             next = NULL;  | 
4848  | 0  |         } else if (cur->type == XML_ELEMENT_NODE) { | 
4849  | 0  |       generic = 0;  | 
4850  | 0  |             sep = "/";  | 
4851  | 0  |             name = (const char *) cur->name;  | 
4852  | 0  |             if (cur->ns) { | 
4853  | 0  |     if (cur->ns->prefix != NULL) { | 
4854  | 0  |                     snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",  | 
4855  | 0  |       (char *)cur->ns->prefix, (char *)cur->name);  | 
4856  | 0  |         nametemp[sizeof(nametemp) - 1] = 0;  | 
4857  | 0  |         name = nametemp;  | 
4858  | 0  |     } else { | 
4859  |  |         /*  | 
4860  |  |         * We cannot express named elements in the default  | 
4861  |  |         * namespace, so use "*".  | 
4862  |  |         */  | 
4863  | 0  |         generic = 1;  | 
4864  | 0  |         name = "*";  | 
4865  | 0  |     }  | 
4866  | 0  |             }  | 
4867  | 0  |             next = cur->parent;  | 
4868  |  |  | 
4869  |  |             /*  | 
4870  |  |              * Thumbler index computation  | 
4871  |  |        * TODO: the occurrence test seems bogus for namespaced names  | 
4872  |  |              */  | 
4873  | 0  |             tmp = cur->prev;  | 
4874  | 0  |             while (tmp != NULL) { | 
4875  | 0  |                 if ((tmp->type == XML_ELEMENT_NODE) &&  | 
4876  | 0  |         (generic ||  | 
4877  | 0  |          (xmlStrEqual(cur->name, tmp->name) &&  | 
4878  | 0  |          ((tmp->ns == cur->ns) ||  | 
4879  | 0  |           ((tmp->ns != NULL) && (cur->ns != NULL) &&  | 
4880  | 0  |            (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))  | 
4881  | 0  |                     occur++;  | 
4882  | 0  |                 tmp = tmp->prev;  | 
4883  | 0  |             }  | 
4884  | 0  |             if (occur == 0) { | 
4885  | 0  |                 tmp = cur->next;  | 
4886  | 0  |                 while (tmp != NULL && occur == 0) { | 
4887  | 0  |                     if ((tmp->type == XML_ELEMENT_NODE) &&  | 
4888  | 0  |       (generic ||  | 
4889  | 0  |        (xmlStrEqual(cur->name, tmp->name) &&  | 
4890  | 0  |        ((tmp->ns == cur->ns) ||  | 
4891  | 0  |         ((tmp->ns != NULL) && (cur->ns != NULL) &&  | 
4892  | 0  |          (xmlStrEqual(cur->ns->prefix, tmp->ns->prefix)))))))  | 
4893  | 0  |                         occur++;  | 
4894  | 0  |                     tmp = tmp->next;  | 
4895  | 0  |                 }  | 
4896  | 0  |                 if (occur != 0)  | 
4897  | 0  |                     occur = 1;  | 
4898  | 0  |             } else  | 
4899  | 0  |                 occur++;  | 
4900  | 0  |         } else if (cur->type == XML_COMMENT_NODE) { | 
4901  | 0  |             sep = "/";  | 
4902  | 0  |       name = "comment()";  | 
4903  | 0  |             next = cur->parent;  | 
4904  |  |  | 
4905  |  |             /*  | 
4906  |  |              * Thumbler index computation  | 
4907  |  |              */  | 
4908  | 0  |             tmp = cur->prev;  | 
4909  | 0  |             while (tmp != NULL) { | 
4910  | 0  |                 if (tmp->type == XML_COMMENT_NODE)  | 
4911  | 0  |         occur++;  | 
4912  | 0  |                 tmp = tmp->prev;  | 
4913  | 0  |             }  | 
4914  | 0  |             if (occur == 0) { | 
4915  | 0  |                 tmp = cur->next;  | 
4916  | 0  |                 while (tmp != NULL && occur == 0) { | 
4917  | 0  |         if (tmp->type == XML_COMMENT_NODE)  | 
4918  | 0  |             occur++;  | 
4919  | 0  |                     tmp = tmp->next;  | 
4920  | 0  |                 }  | 
4921  | 0  |                 if (occur != 0)  | 
4922  | 0  |                     occur = 1;  | 
4923  | 0  |             } else  | 
4924  | 0  |                 occur++;  | 
4925  | 0  |         } else if ((cur->type == XML_TEXT_NODE) ||  | 
4926  | 0  |                    (cur->type == XML_CDATA_SECTION_NODE)) { | 
4927  | 0  |             sep = "/";  | 
4928  | 0  |       name = "text()";  | 
4929  | 0  |             next = cur->parent;  | 
4930  |  |  | 
4931  |  |             /*  | 
4932  |  |              * Thumbler index computation  | 
4933  |  |              */  | 
4934  | 0  |             tmp = cur->prev;  | 
4935  | 0  |             while (tmp != NULL) { | 
4936  | 0  |                 if ((tmp->type == XML_TEXT_NODE) ||  | 
4937  | 0  |         (tmp->type == XML_CDATA_SECTION_NODE))  | 
4938  | 0  |         occur++;  | 
4939  | 0  |                 tmp = tmp->prev;  | 
4940  | 0  |             }  | 
4941  |  |       /*  | 
4942  |  |       * Evaluate if this is the only text- or CDATA-section-node;  | 
4943  |  |       * if yes, then we'll get "text()", otherwise "text()[1]".  | 
4944  |  |       */  | 
4945  | 0  |             if (occur == 0) { | 
4946  | 0  |                 tmp = cur->next;  | 
4947  | 0  |                 while (tmp != NULL) { | 
4948  | 0  |         if ((tmp->type == XML_TEXT_NODE) ||  | 
4949  | 0  |       (tmp->type == XML_CDATA_SECTION_NODE))  | 
4950  | 0  |         { | 
4951  | 0  |       occur = 1;  | 
4952  | 0  |       break;  | 
4953  | 0  |         }  | 
4954  | 0  |         tmp = tmp->next;  | 
4955  | 0  |     }  | 
4956  | 0  |             } else  | 
4957  | 0  |                 occur++;  | 
4958  | 0  |         } else if (cur->type == XML_PI_NODE) { | 
4959  | 0  |             sep = "/";  | 
4960  | 0  |       snprintf(nametemp, sizeof(nametemp) - 1,  | 
4961  | 0  |          "processing-instruction('%s')", (char *)cur->name); | 
4962  | 0  |             nametemp[sizeof(nametemp) - 1] = 0;  | 
4963  | 0  |             name = nametemp;  | 
4964  |  | 
  | 
4965  | 0  |       next = cur->parent;  | 
4966  |  |  | 
4967  |  |             /*  | 
4968  |  |              * Thumbler index computation  | 
4969  |  |              */  | 
4970  | 0  |             tmp = cur->prev;  | 
4971  | 0  |             while (tmp != NULL) { | 
4972  | 0  |                 if ((tmp->type == XML_PI_NODE) &&  | 
4973  | 0  |         (xmlStrEqual(cur->name, tmp->name)))  | 
4974  | 0  |                     occur++;  | 
4975  | 0  |                 tmp = tmp->prev;  | 
4976  | 0  |             }  | 
4977  | 0  |             if (occur == 0) { | 
4978  | 0  |                 tmp = cur->next;  | 
4979  | 0  |                 while (tmp != NULL && occur == 0) { | 
4980  | 0  |                     if ((tmp->type == XML_PI_NODE) &&  | 
4981  | 0  |       (xmlStrEqual(cur->name, tmp->name)))  | 
4982  | 0  |                         occur++;  | 
4983  | 0  |                     tmp = tmp->next;  | 
4984  | 0  |                 }  | 
4985  | 0  |                 if (occur != 0)  | 
4986  | 0  |                     occur = 1;  | 
4987  | 0  |             } else  | 
4988  | 0  |                 occur++;  | 
4989  |  | 
  | 
4990  | 0  |         } else if (cur->type == XML_ATTRIBUTE_NODE) { | 
4991  | 0  |             sep = "/@";  | 
4992  | 0  |             name = (const char *) (((xmlAttrPtr) cur)->name);  | 
4993  | 0  |             if (cur->ns) { | 
4994  | 0  |           if (cur->ns->prefix != NULL)  | 
4995  | 0  |                     snprintf(nametemp, sizeof(nametemp) - 1, "%s:%s",  | 
4996  | 0  |       (char *)cur->ns->prefix, (char *)cur->name);  | 
4997  | 0  |     else  | 
4998  | 0  |         snprintf(nametemp, sizeof(nametemp) - 1, "%s",  | 
4999  | 0  |       (char *)cur->name);  | 
5000  | 0  |                 nametemp[sizeof(nametemp) - 1] = 0;  | 
5001  | 0  |                 name = nametemp;  | 
5002  | 0  |             }  | 
5003  | 0  |             next = ((xmlAttrPtr) cur)->parent;  | 
5004  | 0  |         } else { | 
5005  | 0  |             xmlFree(buf);  | 
5006  | 0  |             xmlFree(buffer);  | 
5007  | 0  |             return (NULL);  | 
5008  | 0  |         }  | 
5009  |  |  | 
5010  |  |         /*  | 
5011  |  |          * Make sure there is enough room  | 
5012  |  |          */  | 
5013  | 0  |         if (xmlStrlen(buffer) + sizeof(nametemp) + 20 > buf_len) { | 
5014  | 0  |             buf_len =  | 
5015  | 0  |                 2 * buf_len + xmlStrlen(buffer) + sizeof(nametemp) + 20;  | 
5016  | 0  |             temp = (xmlChar *) xmlRealloc(buffer, buf_len);  | 
5017  | 0  |             if (temp == NULL) { | 
5018  | 0  |     xmlTreeErrMemory("getting node path"); | 
5019  | 0  |                 xmlFree(buf);  | 
5020  | 0  |                 xmlFree(buffer);  | 
5021  | 0  |                 return (NULL);  | 
5022  | 0  |             }  | 
5023  | 0  |             buffer = temp;  | 
5024  | 0  |             temp = (xmlChar *) xmlRealloc(buf, buf_len);  | 
5025  | 0  |             if (temp == NULL) { | 
5026  | 0  |     xmlTreeErrMemory("getting node path"); | 
5027  | 0  |                 xmlFree(buf);  | 
5028  | 0  |                 xmlFree(buffer);  | 
5029  | 0  |                 return (NULL);  | 
5030  | 0  |             }  | 
5031  | 0  |             buf = temp;  | 
5032  | 0  |         }  | 
5033  | 0  |         if (occur == 0)  | 
5034  | 0  |             snprintf((char *) buf, buf_len, "%s%s%s",  | 
5035  | 0  |                      sep, name, (char *) buffer);  | 
5036  | 0  |         else  | 
5037  | 0  |             snprintf((char *) buf, buf_len, "%s%s[%d]%s",  | 
5038  | 0  |                      sep, name, occur, (char *) buffer);  | 
5039  | 0  |         snprintf((char *) buffer, buf_len, "%s", (char *)buf);  | 
5040  | 0  |         cur = next;  | 
5041  | 0  |     } while (cur != NULL);  | 
5042  | 0  |     xmlFree(buf);  | 
5043  | 0  |     return (buffer);  | 
5044  | 0  | }  | 
5045  |  | #endif /* LIBXML_TREE_ENABLED */  | 
5046  |  |  | 
5047  |  | /**  | 
5048  |  |  * xmlDocGetRootElement:  | 
5049  |  |  * @doc:  the document  | 
5050  |  |  *  | 
5051  |  |  * Get the root element of the document (doc->children is a list  | 
5052  |  |  * containing possibly comments, PIs, etc ...).  | 
5053  |  |  *  | 
5054  |  |  * Returns the #xmlNodePtr for the root or NULL  | 
5055  |  |  */  | 
5056  |  | xmlNodePtr  | 
5057  | 3.41M  | xmlDocGetRootElement(const xmlDoc *doc) { | 
5058  | 3.41M  |     xmlNodePtr ret;  | 
5059  |  |  | 
5060  | 3.41M  |     if (doc == NULL) return(NULL);  | 
5061  | 3.41M  |     ret = doc->children;  | 
5062  | 6.78M  |     while (ret != NULL) { | 
5063  | 6.76M  |   if (ret->type == XML_ELEMENT_NODE)  | 
5064  | 3.39M  |       return(ret);  | 
5065  | 3.37M  |         ret = ret->next;  | 
5066  | 3.37M  |     }  | 
5067  | 18.6k  |     return(ret);  | 
5068  | 3.41M  | }  | 
5069  |  |  | 
5070  |  | #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)  | 
5071  |  | /**  | 
5072  |  |  * xmlDocSetRootElement:  | 
5073  |  |  * @doc:  the document  | 
5074  |  |  * @root:  the new document root element, if root is NULL no action is taken,  | 
5075  |  |  *         to remove a node from a document use xmlUnlinkNode(root) instead.  | 
5076  |  |  *  | 
5077  |  |  * Set the root element of the document (doc->children is a list  | 
5078  |  |  * containing possibly comments, PIs, etc ...).  | 
5079  |  |  *  | 
5080  |  |  * Returns the old root element if any was found, NULL if root was NULL  | 
5081  |  |  */  | 
5082  |  | xmlNodePtr  | 
5083  | 0  | xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) { | 
5084  | 0  |     xmlNodePtr old = NULL;  | 
5085  |  | 
  | 
5086  | 0  |     if (doc == NULL) return(NULL);  | 
5087  | 0  |     if ((root == NULL) || (root->type == XML_NAMESPACE_DECL))  | 
5088  | 0  |   return(NULL);  | 
5089  | 0  |     xmlUnlinkNode(root);  | 
5090  | 0  |     xmlSetTreeDoc(root, doc);  | 
5091  | 0  |     root->parent = (xmlNodePtr) doc;  | 
5092  | 0  |     old = doc->children;  | 
5093  | 0  |     while (old != NULL) { | 
5094  | 0  |   if (old->type == XML_ELEMENT_NODE)  | 
5095  | 0  |       break;  | 
5096  | 0  |         old = old->next;  | 
5097  | 0  |     }  | 
5098  | 0  |     if (old == NULL) { | 
5099  | 0  |   if (doc->children == NULL) { | 
5100  | 0  |       doc->children = root;  | 
5101  | 0  |       doc->last = root;  | 
5102  | 0  |   } else { | 
5103  | 0  |       xmlAddSibling(doc->children, root);  | 
5104  | 0  |   }  | 
5105  | 0  |     } else { | 
5106  | 0  |   xmlReplaceNode(old, root);  | 
5107  | 0  |     }  | 
5108  | 0  |     return(old);  | 
5109  | 0  | }  | 
5110  |  | #endif  | 
5111  |  |  | 
5112  |  | #if defined(LIBXML_TREE_ENABLED)  | 
5113  |  | /**  | 
5114  |  |  * xmlNodeSetLang:  | 
5115  |  |  * @cur:  the node being changed  | 
5116  |  |  * @lang:  the language description  | 
5117  |  |  *  | 
5118  |  |  * Set the language of a node, i.e. the values of the xml:lang  | 
5119  |  |  * attribute.  | 
5120  |  |  */  | 
5121  |  | void  | 
5122  | 0  | xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) { | 
5123  | 0  |     xmlNsPtr ns;  | 
5124  |  | 
  | 
5125  | 0  |     if (cur == NULL) return;  | 
5126  | 0  |     switch(cur->type) { | 
5127  | 0  |         case XML_TEXT_NODE:  | 
5128  | 0  |         case XML_CDATA_SECTION_NODE:  | 
5129  | 0  |         case XML_COMMENT_NODE:  | 
5130  | 0  |         case XML_DOCUMENT_NODE:  | 
5131  | 0  |         case XML_DOCUMENT_TYPE_NODE:  | 
5132  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
5133  | 0  |         case XML_NOTATION_NODE:  | 
5134  | 0  |         case XML_HTML_DOCUMENT_NODE:  | 
5135  | 0  |         case XML_DTD_NODE:  | 
5136  | 0  |         case XML_ELEMENT_DECL:  | 
5137  | 0  |         case XML_ATTRIBUTE_DECL:  | 
5138  | 0  |         case XML_ENTITY_DECL:  | 
5139  | 0  |         case XML_PI_NODE:  | 
5140  | 0  |         case XML_ENTITY_REF_NODE:  | 
5141  | 0  |         case XML_ENTITY_NODE:  | 
5142  | 0  |   case XML_NAMESPACE_DECL:  | 
5143  | 0  |   case XML_XINCLUDE_START:  | 
5144  | 0  |   case XML_XINCLUDE_END:  | 
5145  | 0  |       return;  | 
5146  | 0  |         case XML_ELEMENT_NODE:  | 
5147  | 0  |         case XML_ATTRIBUTE_NODE:  | 
5148  | 0  |       break;  | 
5149  | 0  |     }  | 
5150  | 0  |     ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);  | 
5151  | 0  |     if (ns == NULL)  | 
5152  | 0  |   return;  | 
5153  | 0  |     xmlSetNsProp(cur, ns, BAD_CAST "lang", lang);  | 
5154  | 0  | }  | 
5155  |  | #endif /* LIBXML_TREE_ENABLED */  | 
5156  |  |  | 
5157  |  | /**  | 
5158  |  |  * xmlNodeGetLang:  | 
5159  |  |  * @cur:  the node being checked  | 
5160  |  |  *  | 
5161  |  |  * Searches the language of a node, i.e. the values of the xml:lang  | 
5162  |  |  * attribute or the one carried by the nearest ancestor.  | 
5163  |  |  *  | 
5164  |  |  * Returns a pointer to the lang value, or NULL if not found  | 
5165  |  |  *     It's up to the caller to free the memory with xmlFree().  | 
5166  |  |  */  | 
5167  |  | xmlChar *  | 
5168  | 42.6k  | xmlNodeGetLang(const xmlNode *cur) { | 
5169  | 42.6k  |     xmlChar *lang;  | 
5170  |  |  | 
5171  | 42.6k  |     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))  | 
5172  | 8.35k  |         return(NULL);  | 
5173  | 159k  |     while (cur != NULL) { | 
5174  | 124k  |         lang = xmlGetNsProp(cur, BAD_CAST "lang", XML_XML_NAMESPACE);  | 
5175  | 124k  |   if (lang != NULL)  | 
5176  | 0  |       return(lang);  | 
5177  | 124k  |   cur = cur->parent;  | 
5178  | 124k  |     }  | 
5179  | 34.2k  |     return(NULL);  | 
5180  | 34.2k  | }  | 
5181  |  |  | 
5182  |  |  | 
5183  |  | #ifdef LIBXML_TREE_ENABLED  | 
5184  |  | /**  | 
5185  |  |  * xmlNodeSetSpacePreserve:  | 
5186  |  |  * @cur:  the node being changed  | 
5187  |  |  * @val:  the xml:space value ("0": default, 1: "preserve") | 
5188  |  |  *  | 
5189  |  |  * Set (or reset) the space preserving behaviour of a node, i.e. the  | 
5190  |  |  * value of the xml:space attribute.  | 
5191  |  |  */  | 
5192  |  | void  | 
5193  | 0  | xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) { | 
5194  | 0  |     xmlNsPtr ns;  | 
5195  |  | 
  | 
5196  | 0  |     if (cur == NULL) return;  | 
5197  | 0  |     switch(cur->type) { | 
5198  | 0  |         case XML_TEXT_NODE:  | 
5199  | 0  |         case XML_CDATA_SECTION_NODE:  | 
5200  | 0  |         case XML_COMMENT_NODE:  | 
5201  | 0  |         case XML_DOCUMENT_NODE:  | 
5202  | 0  |         case XML_DOCUMENT_TYPE_NODE:  | 
5203  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
5204  | 0  |         case XML_NOTATION_NODE:  | 
5205  | 0  |         case XML_HTML_DOCUMENT_NODE:  | 
5206  | 0  |         case XML_DTD_NODE:  | 
5207  | 0  |         case XML_ELEMENT_DECL:  | 
5208  | 0  |         case XML_ATTRIBUTE_DECL:  | 
5209  | 0  |         case XML_ENTITY_DECL:  | 
5210  | 0  |         case XML_PI_NODE:  | 
5211  | 0  |         case XML_ENTITY_REF_NODE:  | 
5212  | 0  |         case XML_ENTITY_NODE:  | 
5213  | 0  |   case XML_NAMESPACE_DECL:  | 
5214  | 0  |   case XML_XINCLUDE_START:  | 
5215  | 0  |   case XML_XINCLUDE_END:  | 
5216  | 0  |       return;  | 
5217  | 0  |         case XML_ELEMENT_NODE:  | 
5218  | 0  |         case XML_ATTRIBUTE_NODE:  | 
5219  | 0  |       break;  | 
5220  | 0  |     }  | 
5221  | 0  |     ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);  | 
5222  | 0  |     if (ns == NULL)  | 
5223  | 0  |   return;  | 
5224  | 0  |     switch (val) { | 
5225  | 0  |     case 0:  | 
5226  | 0  |   xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "default");  | 
5227  | 0  |   break;  | 
5228  | 0  |     case 1:  | 
5229  | 0  |   xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "preserve");  | 
5230  | 0  |   break;  | 
5231  | 0  |     }  | 
5232  | 0  | }  | 
5233  |  | #endif /* LIBXML_TREE_ENABLED */  | 
5234  |  |  | 
5235  |  | /**  | 
5236  |  |  * xmlNodeGetSpacePreserve:  | 
5237  |  |  * @cur:  the node being checked  | 
5238  |  |  *  | 
5239  |  |  * Searches the space preserving behaviour of a node, i.e. the values  | 
5240  |  |  * of the xml:space attribute or the one carried by the nearest  | 
5241  |  |  * ancestor.  | 
5242  |  |  *  | 
5243  |  |  * Returns -1 if xml:space is not inherited, 0 if "default", 1 if "preserve"  | 
5244  |  |  */  | 
5245  |  | int  | 
5246  | 0  | xmlNodeGetSpacePreserve(const xmlNode *cur) { | 
5247  | 0  |     xmlChar *space;  | 
5248  |  | 
  | 
5249  | 0  |     if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE))  | 
5250  | 0  |         return(-1);  | 
5251  | 0  |     while (cur != NULL) { | 
5252  | 0  |   space = xmlGetNsProp(cur, BAD_CAST "space", XML_XML_NAMESPACE);  | 
5253  | 0  |   if (space != NULL) { | 
5254  | 0  |       if (xmlStrEqual(space, BAD_CAST "preserve")) { | 
5255  | 0  |     xmlFree(space);  | 
5256  | 0  |     return(1);  | 
5257  | 0  |       }  | 
5258  | 0  |       if (xmlStrEqual(space, BAD_CAST "default")) { | 
5259  | 0  |     xmlFree(space);  | 
5260  | 0  |     return(0);  | 
5261  | 0  |       }  | 
5262  | 0  |       xmlFree(space);  | 
5263  | 0  |   }  | 
5264  | 0  |   cur = cur->parent;  | 
5265  | 0  |     }  | 
5266  | 0  |     return(-1);  | 
5267  | 0  | }  | 
5268  |  |  | 
5269  |  | #ifdef LIBXML_TREE_ENABLED  | 
5270  |  | /**  | 
5271  |  |  * xmlNodeSetName:  | 
5272  |  |  * @cur:  the node being changed  | 
5273  |  |  * @name:  the new tag name  | 
5274  |  |  *  | 
5275  |  |  * Set (or reset) the name of a node.  | 
5276  |  |  */  | 
5277  |  | void  | 
5278  | 0  | xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) { | 
5279  | 0  |     xmlDocPtr doc;  | 
5280  | 0  |     xmlDictPtr dict;  | 
5281  | 0  |     const xmlChar *freeme = NULL;  | 
5282  |  | 
  | 
5283  | 0  |     if (cur == NULL) return;  | 
5284  | 0  |     if (name == NULL) return;  | 
5285  | 0  |     switch(cur->type) { | 
5286  | 0  |         case XML_TEXT_NODE:  | 
5287  | 0  |         case XML_CDATA_SECTION_NODE:  | 
5288  | 0  |         case XML_COMMENT_NODE:  | 
5289  | 0  |         case XML_DOCUMENT_TYPE_NODE:  | 
5290  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
5291  | 0  |         case XML_NOTATION_NODE:  | 
5292  | 0  |         case XML_HTML_DOCUMENT_NODE:  | 
5293  | 0  |   case XML_NAMESPACE_DECL:  | 
5294  | 0  |   case XML_XINCLUDE_START:  | 
5295  | 0  |   case XML_XINCLUDE_END:  | 
5296  | 0  |       return;  | 
5297  | 0  |         case XML_ELEMENT_NODE:  | 
5298  | 0  |         case XML_ATTRIBUTE_NODE:  | 
5299  | 0  |         case XML_PI_NODE:  | 
5300  | 0  |         case XML_ENTITY_REF_NODE:  | 
5301  | 0  |         case XML_ENTITY_NODE:  | 
5302  | 0  |         case XML_DTD_NODE:  | 
5303  | 0  |         case XML_DOCUMENT_NODE:  | 
5304  | 0  |         case XML_ELEMENT_DECL:  | 
5305  | 0  |         case XML_ATTRIBUTE_DECL:  | 
5306  | 0  |         case XML_ENTITY_DECL:  | 
5307  | 0  |       break;  | 
5308  | 0  |     }  | 
5309  | 0  |     doc = cur->doc;  | 
5310  | 0  |     if (doc != NULL)  | 
5311  | 0  |   dict = doc->dict;  | 
5312  | 0  |     else  | 
5313  | 0  |         dict = NULL;  | 
5314  | 0  |     if (dict != NULL) { | 
5315  | 0  |         if ((cur->name != NULL) && (!xmlDictOwns(dict, cur->name)))  | 
5316  | 0  |       freeme = cur->name;  | 
5317  | 0  |   cur->name = xmlDictLookup(dict, name, -1);  | 
5318  | 0  |     } else { | 
5319  | 0  |   if (cur->name != NULL)  | 
5320  | 0  |       freeme = cur->name;  | 
5321  | 0  |   cur->name = xmlStrdup(name);  | 
5322  | 0  |     }  | 
5323  |  | 
  | 
5324  | 0  |     if (freeme)  | 
5325  | 0  |         xmlFree((xmlChar *) freeme);  | 
5326  | 0  | }  | 
5327  |  | #endif  | 
5328  |  |  | 
5329  |  | #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)  | 
5330  |  | /**  | 
5331  |  |  * xmlNodeSetBase:  | 
5332  |  |  * @cur:  the node being changed  | 
5333  |  |  * @uri:  the new base URI  | 
5334  |  |  *  | 
5335  |  |  * Set (or reset) the base URI of a node, i.e. the value of the  | 
5336  |  |  * xml:base attribute.  | 
5337  |  |  */  | 
5338  |  | void  | 
5339  | 0  | xmlNodeSetBase(xmlNodePtr cur, const xmlChar* uri) { | 
5340  | 0  |     xmlNsPtr ns;  | 
5341  | 0  |     xmlChar* fixed;  | 
5342  |  | 
  | 
5343  | 0  |     if (cur == NULL) return;  | 
5344  | 0  |     switch(cur->type) { | 
5345  | 0  |         case XML_TEXT_NODE:  | 
5346  | 0  |         case XML_CDATA_SECTION_NODE:  | 
5347  | 0  |         case XML_COMMENT_NODE:  | 
5348  | 0  |         case XML_DOCUMENT_TYPE_NODE:  | 
5349  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
5350  | 0  |         case XML_NOTATION_NODE:  | 
5351  | 0  |         case XML_DTD_NODE:  | 
5352  | 0  |         case XML_ELEMENT_DECL:  | 
5353  | 0  |         case XML_ATTRIBUTE_DECL:  | 
5354  | 0  |         case XML_ENTITY_DECL:  | 
5355  | 0  |         case XML_PI_NODE:  | 
5356  | 0  |         case XML_ENTITY_REF_NODE:  | 
5357  | 0  |         case XML_ENTITY_NODE:  | 
5358  | 0  |   case XML_NAMESPACE_DECL:  | 
5359  | 0  |   case XML_XINCLUDE_START:  | 
5360  | 0  |   case XML_XINCLUDE_END:  | 
5361  | 0  |       return;  | 
5362  | 0  |         case XML_ELEMENT_NODE:  | 
5363  | 0  |         case XML_ATTRIBUTE_NODE:  | 
5364  | 0  |       break;  | 
5365  | 0  |         case XML_DOCUMENT_NODE:  | 
5366  | 0  |         case XML_HTML_DOCUMENT_NODE: { | 
5367  | 0  |       xmlDocPtr doc = (xmlDocPtr) cur;  | 
5368  |  | 
  | 
5369  | 0  |       if (doc->URL != NULL)  | 
5370  | 0  |     xmlFree((xmlChar *) doc->URL);  | 
5371  | 0  |       if (uri == NULL)  | 
5372  | 0  |     doc->URL = NULL;  | 
5373  | 0  |       else  | 
5374  | 0  |     doc->URL = xmlPathToURI(uri);  | 
5375  | 0  |       return;  | 
5376  | 0  |   }  | 
5377  | 0  |     }  | 
5378  |  |  | 
5379  | 0  |     ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE);  | 
5380  | 0  |     if (ns == NULL)  | 
5381  | 0  |   return;  | 
5382  | 0  |     fixed = xmlPathToURI(uri);  | 
5383  | 0  |     if (fixed != NULL) { | 
5384  | 0  |   xmlSetNsProp(cur, ns, BAD_CAST "base", fixed);  | 
5385  | 0  |   xmlFree(fixed);  | 
5386  | 0  |     } else { | 
5387  | 0  |   xmlSetNsProp(cur, ns, BAD_CAST "base", uri);  | 
5388  | 0  |     }  | 
5389  | 0  | }  | 
5390  |  | #endif /* LIBXML_TREE_ENABLED */  | 
5391  |  |  | 
5392  |  | /**  | 
5393  |  |  * xmlNodeGetBase:  | 
5394  |  |  * @doc:  the document the node pertains to  | 
5395  |  |  * @cur:  the node being checked  | 
5396  |  |  *  | 
5397  |  |  * Searches for the BASE URL. The code should work on both XML  | 
5398  |  |  * and HTML document even if base mechanisms are completely different.  | 
5399  |  |  * It returns the base as defined in RFC 2396 sections  | 
5400  |  |  * 5.1.1. Base URI within Document Content  | 
5401  |  |  * and  | 
5402  |  |  * 5.1.2. Base URI from the Encapsulating Entity  | 
5403  |  |  * However it does not return the document base (5.1.3), use  | 
5404  |  |  * doc->URL in this case  | 
5405  |  |  *  | 
5406  |  |  * Returns a pointer to the base URL, or NULL if not found  | 
5407  |  |  *     It's up to the caller to free the memory with xmlFree().  | 
5408  |  |  */  | 
5409  |  | xmlChar *  | 
5410  | 3.60M  | xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur) { | 
5411  | 3.60M  |     xmlChar *oldbase = NULL;  | 
5412  | 3.60M  |     xmlChar *base, *newbase;  | 
5413  |  |  | 
5414  | 3.60M  |     if ((cur == NULL) && (doc == NULL))  | 
5415  | 0  |         return(NULL);  | 
5416  | 3.60M  |     if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))  | 
5417  | 0  |         return(NULL);  | 
5418  | 3.60M  |     if (doc == NULL) doc = cur->doc;  | 
5419  | 3.60M  |     if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) { | 
5420  | 0  |         cur = doc->children;  | 
5421  | 0  |   while ((cur != NULL) && (cur->name != NULL)) { | 
5422  | 0  |       if (cur->type != XML_ELEMENT_NODE) { | 
5423  | 0  |           cur = cur->next;  | 
5424  | 0  |     continue;  | 
5425  | 0  |       }  | 
5426  | 0  |       if (!xmlStrcasecmp(cur->name, BAD_CAST "html")) { | 
5427  | 0  |           cur = cur->children;  | 
5428  | 0  |     continue;  | 
5429  | 0  |       }  | 
5430  | 0  |       if (!xmlStrcasecmp(cur->name, BAD_CAST "head")) { | 
5431  | 0  |           cur = cur->children;  | 
5432  | 0  |     continue;  | 
5433  | 0  |       }  | 
5434  | 0  |       if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) { | 
5435  | 0  |                 return(xmlGetProp(cur, BAD_CAST "href"));  | 
5436  | 0  |       }  | 
5437  | 0  |       cur = cur->next;  | 
5438  | 0  |   }  | 
5439  | 0  |   return(NULL);  | 
5440  | 0  |     }  | 
5441  | 10.8M  |     while (cur != NULL) { | 
5442  | 7.26M  |   if (cur->type == XML_ENTITY_DECL) { | 
5443  | 0  |       xmlEntityPtr ent = (xmlEntityPtr) cur;  | 
5444  | 0  |       return(xmlStrdup(ent->URI));  | 
5445  | 0  |   }  | 
5446  | 7.26M  |   if (cur->type == XML_ELEMENT_NODE) { | 
5447  | 3.60M  |       base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);  | 
5448  | 3.60M  |       if (base != NULL) { | 
5449  | 0  |     if (oldbase != NULL) { | 
5450  | 0  |         newbase = xmlBuildURI(oldbase, base);  | 
5451  | 0  |         if (newbase != NULL) { | 
5452  | 0  |       xmlFree(oldbase);  | 
5453  | 0  |       xmlFree(base);  | 
5454  | 0  |       oldbase = newbase;  | 
5455  | 0  |         } else { | 
5456  | 0  |       xmlFree(oldbase);  | 
5457  | 0  |       xmlFree(base);  | 
5458  | 0  |       return(NULL);  | 
5459  | 0  |         }  | 
5460  | 0  |     } else { | 
5461  | 0  |         oldbase = base;  | 
5462  | 0  |     }  | 
5463  | 0  |     if ((!xmlStrncmp(oldbase, BAD_CAST "http://", 7)) ||  | 
5464  | 0  |         (!xmlStrncmp(oldbase, BAD_CAST "ftp://", 6)) ||  | 
5465  | 0  |         (!xmlStrncmp(oldbase, BAD_CAST "urn:", 4)))  | 
5466  | 0  |         return(oldbase);  | 
5467  | 0  |       }  | 
5468  | 3.60M  |   }  | 
5469  | 7.26M  |   cur = cur->parent;  | 
5470  | 7.26M  |     }  | 
5471  | 3.60M  |     if ((doc != NULL) && (doc->URL != NULL)) { | 
5472  | 2.41M  |   if (oldbase == NULL)  | 
5473  | 2.41M  |       return(xmlStrdup(doc->URL));  | 
5474  | 0  |   newbase = xmlBuildURI(oldbase, doc->URL);  | 
5475  | 0  |   xmlFree(oldbase);  | 
5476  | 0  |   return(newbase);  | 
5477  | 2.41M  |     }  | 
5478  | 1.18M  |     return(oldbase);  | 
5479  | 3.60M  | }  | 
5480  |  |  | 
5481  |  | /**  | 
5482  |  |  * xmlNodeBufGetContent:  | 
5483  |  |  * @buffer:  a buffer  | 
5484  |  |  * @cur:  the node being read  | 
5485  |  |  *  | 
5486  |  |  * Read the value of a node @cur, this can be either the text carried  | 
5487  |  |  * directly by this node if it's a TEXT node or the aggregate string  | 
5488  |  |  * of the values carried by this node child's (TEXT and ENTITY_REF).  | 
5489  |  |  * Entity references are substituted.  | 
5490  |  |  * Fills up the buffer @buffer with this value  | 
5491  |  |  *  | 
5492  |  |  * Returns 0 in case of success and -1 in case of error.  | 
5493  |  |  */  | 
5494  |  | int  | 
5495  |  | xmlNodeBufGetContent(xmlBufferPtr buffer, const xmlNode *cur)  | 
5496  | 0  | { | 
5497  | 0  |     xmlBufPtr buf;  | 
5498  | 0  |     int ret;  | 
5499  |  | 
  | 
5500  | 0  |     if ((cur == NULL) || (buffer == NULL)) return(-1);  | 
5501  | 0  |     buf = xmlBufFromBuffer(buffer);  | 
5502  | 0  |     ret = xmlBufGetNodeContent(buf, cur);  | 
5503  | 0  |     buffer = xmlBufBackToBuffer(buf);  | 
5504  | 0  |     if ((ret < 0) || (buffer == NULL))  | 
5505  | 0  |         return(-1);  | 
5506  | 0  |     return(0);  | 
5507  | 0  | }  | 
5508  |  |  | 
5509  |  | /**  | 
5510  |  |  * xmlBufGetNodeContent:  | 
5511  |  |  * @buf:  a buffer xmlBufPtr  | 
5512  |  |  * @cur:  the node being read  | 
5513  |  |  *  | 
5514  |  |  * Read the value of a node @cur, this can be either the text carried  | 
5515  |  |  * directly by this node if it's a TEXT node or the aggregate string  | 
5516  |  |  * of the values carried by this node child's (TEXT and ENTITY_REF).  | 
5517  |  |  * Entity references are substituted.  | 
5518  |  |  * Fills up the buffer @buf with this value  | 
5519  |  |  *  | 
5520  |  |  * Returns 0 in case of success and -1 in case of error.  | 
5521  |  |  */  | 
5522  |  | int  | 
5523  |  | xmlBufGetNodeContent(xmlBufPtr buf, const xmlNode *cur)  | 
5524  | 181M  | { | 
5525  | 181M  |     if ((cur == NULL) || (buf == NULL)) return(-1);  | 
5526  | 181M  |     switch (cur->type) { | 
5527  | 0  |         case XML_CDATA_SECTION_NODE:  | 
5528  | 313  |         case XML_TEXT_NODE:  | 
5529  | 313  |       xmlBufCat(buf, cur->content);  | 
5530  | 313  |             break;  | 
5531  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
5532  | 180M  |         case XML_ELEMENT_NODE:{ | 
5533  | 180M  |                 const xmlNode *tmp = cur;  | 
5534  |  |  | 
5535  | 591M  |                 while (tmp != NULL) { | 
5536  | 412M  |                     switch (tmp->type) { | 
5537  | 1.86M  |                         case XML_CDATA_SECTION_NODE:  | 
5538  | 211M  |                         case XML_TEXT_NODE:  | 
5539  | 211M  |                             if (tmp->content != NULL)  | 
5540  | 211M  |                                 xmlBufCat(buf, tmp->content);  | 
5541  | 211M  |                             break;  | 
5542  | 0  |                         case XML_ENTITY_REF_NODE:  | 
5543  | 0  |                             xmlBufGetNodeContent(buf, tmp);  | 
5544  | 0  |                             break;  | 
5545  | 200M  |                         default:  | 
5546  | 200M  |                             break;  | 
5547  | 412M  |                     }  | 
5548  |  |                     /*  | 
5549  |  |                      * Skip to next node  | 
5550  |  |                      */  | 
5551  | 412M  |                     if (tmp->children != NULL) { | 
5552  | 191M  |                         if (tmp->children->type != XML_ENTITY_DECL) { | 
5553  | 191M  |                             tmp = tmp->children;  | 
5554  | 191M  |                             continue;  | 
5555  | 191M  |                         }  | 
5556  | 191M  |                     }  | 
5557  | 220M  |                     if (tmp == cur)  | 
5558  | 875k  |                         break;  | 
5559  |  |  | 
5560  | 220M  |                     if (tmp->next != NULL) { | 
5561  | 28.5M  |                         tmp = tmp->next;  | 
5562  | 28.5M  |                         continue;  | 
5563  | 28.5M  |                     }  | 
5564  |  |  | 
5565  | 191M  |                     do { | 
5566  | 191M  |                         tmp = tmp->parent;  | 
5567  | 191M  |                         if (tmp == NULL)  | 
5568  | 0  |                             break;  | 
5569  | 191M  |                         if (tmp == cur) { | 
5570  | 179M  |                             tmp = NULL;  | 
5571  | 179M  |                             break;  | 
5572  | 179M  |                         }  | 
5573  | 12.1M  |                         if (tmp->next != NULL) { | 
5574  | 12.1M  |                             tmp = tmp->next;  | 
5575  | 12.1M  |                             break;  | 
5576  | 12.1M  |                         }  | 
5577  | 12.1M  |                     } while (tmp != NULL);  | 
5578  | 191M  |                 }  | 
5579  | 180M  |     break;  | 
5580  | 180M  |             }  | 
5581  | 180M  |         case XML_ATTRIBUTE_NODE:{ | 
5582  | 0  |                 xmlAttrPtr attr = (xmlAttrPtr) cur;  | 
5583  | 0  |     xmlNodePtr tmp = attr->children;  | 
5584  |  | 
  | 
5585  | 0  |     while (tmp != NULL) { | 
5586  | 0  |         if (tmp->type == XML_TEXT_NODE)  | 
5587  | 0  |             xmlBufCat(buf, tmp->content);  | 
5588  | 0  |         else  | 
5589  | 0  |             xmlBufGetNodeContent(buf, tmp);  | 
5590  | 0  |         tmp = tmp->next;  | 
5591  | 0  |     }  | 
5592  | 0  |                 break;  | 
5593  | 180M  |             }  | 
5594  | 0  |         case XML_COMMENT_NODE:  | 
5595  | 0  |         case XML_PI_NODE:  | 
5596  | 0  |       xmlBufCat(buf, cur->content);  | 
5597  | 0  |             break;  | 
5598  | 0  |         case XML_ENTITY_REF_NODE:{ | 
5599  | 0  |                 xmlEntityPtr ent;  | 
5600  | 0  |                 xmlNodePtr tmp;  | 
5601  |  |  | 
5602  |  |                 /* lookup entity declaration */  | 
5603  | 0  |                 ent = xmlGetDocEntity(cur->doc, cur->name);  | 
5604  | 0  |                 if (ent == NULL)  | 
5605  | 0  |                     return(-1);  | 
5606  |  |  | 
5607  |  |                 /* an entity content can be any "well balanced chunk",  | 
5608  |  |                  * i.e. the result of the content [43] production:  | 
5609  |  |                  * http://www.w3.org/TR/REC-xml#NT-content  | 
5610  |  |                  * -> we iterate through child nodes and recursive call  | 
5611  |  |                  * xmlNodeGetContent() which handles all possible node types */  | 
5612  | 0  |                 tmp = ent->children;  | 
5613  | 0  |                 while (tmp) { | 
5614  | 0  |         xmlBufGetNodeContent(buf, tmp);  | 
5615  | 0  |                     tmp = tmp->next;  | 
5616  | 0  |                 }  | 
5617  | 0  |     break;  | 
5618  | 0  |             }  | 
5619  | 0  |         case XML_ENTITY_NODE:  | 
5620  | 0  |         case XML_DOCUMENT_TYPE_NODE:  | 
5621  | 0  |         case XML_NOTATION_NODE:  | 
5622  | 0  |         case XML_DTD_NODE:  | 
5623  | 0  |         case XML_XINCLUDE_START:  | 
5624  | 0  |         case XML_XINCLUDE_END:  | 
5625  | 0  |             break;  | 
5626  | 791k  |         case XML_DOCUMENT_NODE:  | 
5627  | 791k  |         case XML_HTML_DOCUMENT_NODE:  | 
5628  | 791k  |       cur = cur->children;  | 
5629  | 176M  |       while (cur!= NULL) { | 
5630  | 175M  |     if ((cur->type == XML_ELEMENT_NODE) ||  | 
5631  | 175M  |         (cur->type == XML_TEXT_NODE) ||  | 
5632  | 175M  |         (cur->type == XML_CDATA_SECTION_NODE)) { | 
5633  | 174M  |         xmlBufGetNodeContent(buf, cur);  | 
5634  | 174M  |     }  | 
5635  | 175M  |     cur = cur->next;  | 
5636  | 175M  |       }  | 
5637  | 791k  |       break;  | 
5638  | 0  |         case XML_NAMESPACE_DECL:  | 
5639  | 0  |       xmlBufCat(buf, ((xmlNsPtr) cur)->href);  | 
5640  | 0  |       break;  | 
5641  | 0  |         case XML_ELEMENT_DECL:  | 
5642  | 0  |         case XML_ATTRIBUTE_DECL:  | 
5643  | 0  |         case XML_ENTITY_DECL:  | 
5644  | 0  |             break;  | 
5645  | 181M  |     }  | 
5646  | 181M  |     return(0);  | 
5647  | 181M  | }  | 
5648  |  |  | 
5649  |  | /**  | 
5650  |  |  * xmlNodeGetContent:  | 
5651  |  |  * @cur:  the node being read  | 
5652  |  |  *  | 
5653  |  |  * Read the value of a node, this can be either the text carried  | 
5654  |  |  * directly by this node if it's a TEXT node or the aggregate string  | 
5655  |  |  * of the values carried by this node child's (TEXT and ENTITY_REF).  | 
5656  |  |  * Entity references are substituted.  | 
5657  |  |  * Returns a new #xmlChar * or NULL if no content is available.  | 
5658  |  |  *     It's up to the caller to free the memory with xmlFree().  | 
5659  |  |  */  | 
5660  |  | xmlChar *  | 
5661  |  | xmlNodeGetContent(const xmlNode *cur)  | 
5662  | 10.2M  | { | 
5663  | 10.2M  |     if (cur == NULL)  | 
5664  | 0  |         return (NULL);  | 
5665  | 10.2M  |     switch (cur->type) { | 
5666  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
5667  | 5.35M  |         case XML_ELEMENT_NODE:{ | 
5668  | 5.35M  |                 xmlBufPtr buf;  | 
5669  | 5.35M  |                 xmlChar *ret;  | 
5670  |  |  | 
5671  | 5.35M  |                 buf = xmlBufCreateSize(64);  | 
5672  | 5.35M  |                 if (buf == NULL)  | 
5673  | 0  |                     return (NULL);  | 
5674  | 5.35M  |                 xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);  | 
5675  | 5.35M  |     xmlBufGetNodeContent(buf, cur);  | 
5676  | 5.35M  |                 ret = xmlBufDetach(buf);  | 
5677  | 5.35M  |                 xmlBufFree(buf);  | 
5678  | 5.35M  |                 return (ret);  | 
5679  | 5.35M  |             }  | 
5680  | 786k  |         case XML_ATTRIBUTE_NODE:  | 
5681  | 786k  |       return(xmlGetPropNodeValueInternal((xmlAttrPtr) cur));  | 
5682  | 177k  |         case XML_COMMENT_NODE:  | 
5683  | 553k  |         case XML_PI_NODE:  | 
5684  | 553k  |             if (cur->content != NULL)  | 
5685  | 553k  |                 return (xmlStrdup(cur->content));  | 
5686  | 0  |             return (NULL);  | 
5687  | 0  |         case XML_ENTITY_REF_NODE:{ | 
5688  | 0  |                 xmlEntityPtr ent;  | 
5689  | 0  |                 xmlBufPtr buf;  | 
5690  | 0  |                 xmlChar *ret;  | 
5691  |  |  | 
5692  |  |                 /* lookup entity declaration */  | 
5693  | 0  |                 ent = xmlGetDocEntity(cur->doc, cur->name);  | 
5694  | 0  |                 if (ent == NULL)  | 
5695  | 0  |                     return (NULL);  | 
5696  |  |  | 
5697  | 0  |                 buf = xmlBufCreate();  | 
5698  | 0  |                 if (buf == NULL)  | 
5699  | 0  |                     return (NULL);  | 
5700  | 0  |                 xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);  | 
5701  |  | 
  | 
5702  | 0  |                 xmlBufGetNodeContent(buf, cur);  | 
5703  |  | 
  | 
5704  | 0  |                 ret = xmlBufDetach(buf);  | 
5705  | 0  |                 xmlBufFree(buf);  | 
5706  | 0  |                 return (ret);  | 
5707  | 0  |             }  | 
5708  | 0  |         case XML_ENTITY_NODE:  | 
5709  | 0  |         case XML_DOCUMENT_TYPE_NODE:  | 
5710  | 0  |         case XML_NOTATION_NODE:  | 
5711  | 0  |         case XML_DTD_NODE:  | 
5712  | 0  |         case XML_XINCLUDE_START:  | 
5713  | 0  |         case XML_XINCLUDE_END:  | 
5714  | 0  |             return (NULL);  | 
5715  | 791k  |         case XML_DOCUMENT_NODE:  | 
5716  | 791k  |         case XML_HTML_DOCUMENT_NODE: { | 
5717  | 791k  |       xmlBufPtr buf;  | 
5718  | 791k  |       xmlChar *ret;  | 
5719  |  |  | 
5720  | 791k  |       buf = xmlBufCreate();  | 
5721  | 791k  |       if (buf == NULL)  | 
5722  | 0  |     return (NULL);  | 
5723  | 791k  |             xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);  | 
5724  |  |  | 
5725  | 791k  |       xmlBufGetNodeContent(buf, (xmlNodePtr) cur);  | 
5726  |  |  | 
5727  | 791k  |       ret = xmlBufDetach(buf);  | 
5728  | 791k  |       xmlBufFree(buf);  | 
5729  | 791k  |       return (ret);  | 
5730  | 791k  |   }  | 
5731  | 131k  |         case XML_NAMESPACE_DECL: { | 
5732  | 131k  |       xmlChar *tmp;  | 
5733  |  |  | 
5734  | 131k  |       tmp = xmlStrdup(((xmlNsPtr) cur)->href);  | 
5735  | 131k  |             return (tmp);  | 
5736  | 791k  |   }  | 
5737  | 0  |         case XML_ELEMENT_DECL:  | 
5738  |  |             /* TODO !!! */  | 
5739  | 0  |             return (NULL);  | 
5740  | 0  |         case XML_ATTRIBUTE_DECL:  | 
5741  |  |             /* TODO !!! */  | 
5742  | 0  |             return (NULL);  | 
5743  | 0  |         case XML_ENTITY_DECL:  | 
5744  |  |             /* TODO !!! */  | 
5745  | 0  |             return (NULL);  | 
5746  | 112k  |         case XML_CDATA_SECTION_NODE:  | 
5747  | 2.67M  |         case XML_TEXT_NODE:  | 
5748  | 2.67M  |             if (cur->content != NULL)  | 
5749  | 2.67M  |                 return (xmlStrdup(cur->content));  | 
5750  | 0  |             return (NULL);  | 
5751  | 10.2M  |     }  | 
5752  | 0  |     return (NULL);  | 
5753  | 10.2M  | }  | 
5754  |  |  | 
5755  |  | /**  | 
5756  |  |  * xmlNodeSetContent:  | 
5757  |  |  * @cur:  the node being modified  | 
5758  |  |  * @content:  the new value of the content  | 
5759  |  |  *  | 
5760  |  |  * Replace the content of a node.  | 
5761  |  |  * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity  | 
5762  |  |  *       references, but XML special chars need to be escaped first by using  | 
5763  |  |  *       xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().  | 
5764  |  |  */  | 
5765  |  | void  | 
5766  | 0  | xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) { | 
5767  | 0  |     if (cur == NULL) { | 
5768  |  | #ifdef DEBUG_TREE  | 
5769  |  |         xmlGenericError(xmlGenericErrorContext,  | 
5770  |  |     "xmlNodeSetContent : node == NULL\n");  | 
5771  |  | #endif  | 
5772  | 0  |   return;  | 
5773  | 0  |     }  | 
5774  | 0  |     switch (cur->type) { | 
5775  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
5776  | 0  |         case XML_ELEMENT_NODE:  | 
5777  | 0  |         case XML_ATTRIBUTE_NODE:  | 
5778  | 0  |       if (cur->children != NULL) xmlFreeNodeList(cur->children);  | 
5779  | 0  |       cur->children = xmlStringGetNodeList(cur->doc, content);  | 
5780  | 0  |       UPDATE_LAST_CHILD_AND_PARENT(cur)  | 
5781  | 0  |       break;  | 
5782  | 0  |         case XML_TEXT_NODE:  | 
5783  | 0  |         case XML_CDATA_SECTION_NODE:  | 
5784  | 0  |         case XML_ENTITY_REF_NODE:  | 
5785  | 0  |         case XML_ENTITY_NODE:  | 
5786  | 0  |         case XML_PI_NODE:  | 
5787  | 0  |         case XML_COMMENT_NODE:  | 
5788  | 0  |       if ((cur->content != NULL) &&  | 
5789  | 0  |           (cur->content != (xmlChar *) &(cur->properties))) { | 
5790  | 0  |           if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&  | 
5791  | 0  |         (xmlDictOwns(cur->doc->dict, cur->content))))  | 
5792  | 0  |         xmlFree(cur->content);  | 
5793  | 0  |       }  | 
5794  | 0  |       if (cur->children != NULL) xmlFreeNodeList(cur->children);  | 
5795  | 0  |       cur->last = cur->children = NULL;  | 
5796  | 0  |       if (content != NULL) { | 
5797  | 0  |     cur->content = xmlStrdup(content);  | 
5798  | 0  |       } else  | 
5799  | 0  |     cur->content = NULL;  | 
5800  | 0  |       cur->properties = NULL;  | 
5801  | 0  |       break;  | 
5802  | 0  |         case XML_DOCUMENT_NODE:  | 
5803  | 0  |         case XML_HTML_DOCUMENT_NODE:  | 
5804  | 0  |         case XML_DOCUMENT_TYPE_NODE:  | 
5805  | 0  |   case XML_XINCLUDE_START:  | 
5806  | 0  |   case XML_XINCLUDE_END:  | 
5807  | 0  |       break;  | 
5808  | 0  |         case XML_NOTATION_NODE:  | 
5809  | 0  |       break;  | 
5810  | 0  |         case XML_DTD_NODE:  | 
5811  | 0  |       break;  | 
5812  | 0  |   case XML_NAMESPACE_DECL:  | 
5813  | 0  |       break;  | 
5814  | 0  |         case XML_ELEMENT_DECL:  | 
5815  |  |       /* TODO !!! */  | 
5816  | 0  |       break;  | 
5817  | 0  |         case XML_ATTRIBUTE_DECL:  | 
5818  |  |       /* TODO !!! */  | 
5819  | 0  |       break;  | 
5820  | 0  |         case XML_ENTITY_DECL:  | 
5821  |  |       /* TODO !!! */  | 
5822  | 0  |       break;  | 
5823  | 0  |     }  | 
5824  | 0  | }  | 
5825  |  |  | 
5826  |  | #ifdef LIBXML_TREE_ENABLED  | 
5827  |  | /**  | 
5828  |  |  * xmlNodeSetContentLen:  | 
5829  |  |  * @cur:  the node being modified  | 
5830  |  |  * @content:  the new value of the content  | 
5831  |  |  * @len:  the size of @content  | 
5832  |  |  *  | 
5833  |  |  * Replace the content of a node.  | 
5834  |  |  * NOTE: @content is supposed to be a piece of XML CDATA, so it allows entity  | 
5835  |  |  *       references, but XML special chars need to be escaped first by using  | 
5836  |  |  *       xmlEncodeEntitiesReentrant() resp. xmlEncodeSpecialChars().  | 
5837  |  |  */  | 
5838  |  | void  | 
5839  | 0  | xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) { | 
5840  | 0  |     if (cur == NULL) { | 
5841  |  | #ifdef DEBUG_TREE  | 
5842  |  |         xmlGenericError(xmlGenericErrorContext,  | 
5843  |  |     "xmlNodeSetContentLen : node == NULL\n");  | 
5844  |  | #endif  | 
5845  | 0  |   return;  | 
5846  | 0  |     }  | 
5847  | 0  |     switch (cur->type) { | 
5848  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
5849  | 0  |         case XML_ELEMENT_NODE:  | 
5850  | 0  |         case XML_ATTRIBUTE_NODE:  | 
5851  | 0  |       if (cur->children != NULL) xmlFreeNodeList(cur->children);  | 
5852  | 0  |       cur->children = xmlStringLenGetNodeList(cur->doc, content, len);  | 
5853  | 0  |       UPDATE_LAST_CHILD_AND_PARENT(cur)  | 
5854  | 0  |       break;  | 
5855  | 0  |         case XML_TEXT_NODE:  | 
5856  | 0  |         case XML_CDATA_SECTION_NODE:  | 
5857  | 0  |         case XML_ENTITY_REF_NODE:  | 
5858  | 0  |         case XML_ENTITY_NODE:  | 
5859  | 0  |         case XML_PI_NODE:  | 
5860  | 0  |         case XML_COMMENT_NODE:  | 
5861  | 0  |         case XML_NOTATION_NODE:  | 
5862  | 0  |       if ((cur->content != NULL) &&  | 
5863  | 0  |           (cur->content != (xmlChar *) &(cur->properties))) { | 
5864  | 0  |           if (!((cur->doc != NULL) && (cur->doc->dict != NULL) &&  | 
5865  | 0  |         (xmlDictOwns(cur->doc->dict, cur->content))))  | 
5866  | 0  |         xmlFree(cur->content);  | 
5867  | 0  |       }  | 
5868  | 0  |       if (cur->children != NULL) xmlFreeNodeList(cur->children);  | 
5869  | 0  |       cur->children = cur->last = NULL;  | 
5870  | 0  |       if (content != NULL) { | 
5871  | 0  |     cur->content = xmlStrndup(content, len);  | 
5872  | 0  |       } else  | 
5873  | 0  |     cur->content = NULL;  | 
5874  | 0  |       cur->properties = NULL;  | 
5875  | 0  |       break;  | 
5876  | 0  |         case XML_DOCUMENT_NODE:  | 
5877  | 0  |         case XML_DTD_NODE:  | 
5878  | 0  |         case XML_HTML_DOCUMENT_NODE:  | 
5879  | 0  |         case XML_DOCUMENT_TYPE_NODE:  | 
5880  | 0  |   case XML_NAMESPACE_DECL:  | 
5881  | 0  |   case XML_XINCLUDE_START:  | 
5882  | 0  |   case XML_XINCLUDE_END:  | 
5883  | 0  |       break;  | 
5884  | 0  |         case XML_ELEMENT_DECL:  | 
5885  |  |       /* TODO !!! */  | 
5886  | 0  |       break;  | 
5887  | 0  |         case XML_ATTRIBUTE_DECL:  | 
5888  |  |       /* TODO !!! */  | 
5889  | 0  |       break;  | 
5890  | 0  |         case XML_ENTITY_DECL:  | 
5891  |  |       /* TODO !!! */  | 
5892  | 0  |       break;  | 
5893  | 0  |     }  | 
5894  | 0  | }  | 
5895  |  | #endif /* LIBXML_TREE_ENABLED */  | 
5896  |  |  | 
5897  |  | /**  | 
5898  |  |  * xmlNodeAddContentLen:  | 
5899  |  |  * @cur:  the node being modified  | 
5900  |  |  * @content:  extra content  | 
5901  |  |  * @len:  the size of @content  | 
5902  |  |  *  | 
5903  |  |  * Append the extra substring to the node content.  | 
5904  |  |  * NOTE: In contrast to xmlNodeSetContentLen(), @content is supposed to be  | 
5905  |  |  *       raw text, so unescaped XML special chars are allowed, entity  | 
5906  |  |  *       references are not supported.  | 
5907  |  |  */  | 
5908  |  | void  | 
5909  | 0  | xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) { | 
5910  | 0  |     if (cur == NULL) { | 
5911  |  | #ifdef DEBUG_TREE  | 
5912  |  |         xmlGenericError(xmlGenericErrorContext,  | 
5913  |  |     "xmlNodeAddContentLen : node == NULL\n");  | 
5914  |  | #endif  | 
5915  | 0  |   return;  | 
5916  | 0  |     }  | 
5917  | 0  |     if (len <= 0) return;  | 
5918  | 0  |     switch (cur->type) { | 
5919  | 0  |         case XML_DOCUMENT_FRAG_NODE:  | 
5920  | 0  |         case XML_ELEMENT_NODE: { | 
5921  | 0  |       xmlNodePtr last, newNode, tmp;  | 
5922  |  | 
  | 
5923  | 0  |       last = cur->last;  | 
5924  | 0  |       newNode = xmlNewDocTextLen(cur->doc, content, len);  | 
5925  | 0  |       if (newNode != NULL) { | 
5926  | 0  |     tmp = xmlAddChild(cur, newNode);  | 
5927  | 0  |     if (tmp != newNode)  | 
5928  | 0  |         return;  | 
5929  | 0  |           if ((last != NULL) && (last->next == newNode)) { | 
5930  | 0  |         xmlTextMerge(last, newNode);  | 
5931  | 0  |     }  | 
5932  | 0  |       }  | 
5933  | 0  |       break;  | 
5934  | 0  |   }  | 
5935  | 0  |         case XML_ATTRIBUTE_NODE:  | 
5936  | 0  |       break;  | 
5937  | 0  |         case XML_TEXT_NODE:  | 
5938  | 0  |         case XML_CDATA_SECTION_NODE:  | 
5939  | 0  |         case XML_ENTITY_REF_NODE:  | 
5940  | 0  |         case XML_ENTITY_NODE:  | 
5941  | 0  |         case XML_PI_NODE:  | 
5942  | 0  |         case XML_COMMENT_NODE:  | 
5943  | 0  |         case XML_NOTATION_NODE:  | 
5944  | 0  |       if (content != NULL) { | 
5945  | 0  |           if ((cur->content == (xmlChar *) &(cur->properties)) ||  | 
5946  | 0  |         ((cur->doc != NULL) && (cur->doc->dict != NULL) &&  | 
5947  | 0  |           xmlDictOwns(cur->doc->dict, cur->content))) { | 
5948  | 0  |         cur->content = xmlStrncatNew(cur->content, content, len);  | 
5949  | 0  |         cur->properties = NULL;  | 
5950  | 0  |     } else { | 
5951  | 0  |         cur->content = xmlStrncat(cur->content, content, len);  | 
5952  | 0  |                 }  | 
5953  | 0  |             }  | 
5954  | 0  |       break;  | 
5955  | 0  |         case XML_DOCUMENT_NODE:  | 
5956  | 0  |         case XML_DTD_NODE:  | 
5957  | 0  |         case XML_HTML_DOCUMENT_NODE:  | 
5958  | 0  |         case XML_DOCUMENT_TYPE_NODE:  | 
5959  | 0  |   case XML_NAMESPACE_DECL:  | 
5960  | 0  |   case XML_XINCLUDE_START:  | 
5961  | 0  |   case XML_XINCLUDE_END:  | 
5962  | 0  |       break;  | 
5963  | 0  |         case XML_ELEMENT_DECL:  | 
5964  | 0  |         case XML_ATTRIBUTE_DECL:  | 
5965  | 0  |         case XML_ENTITY_DECL:  | 
5966  | 0  |       break;  | 
5967  | 0  |     }  | 
5968  | 0  | }  | 
5969  |  |  | 
5970  |  | /**  | 
5971  |  |  * xmlNodeAddContent:  | 
5972  |  |  * @cur:  the node being modified  | 
5973  |  |  * @content:  extra content  | 
5974  |  |  *  | 
5975  |  |  * Append the extra substring to the node content.  | 
5976  |  |  * NOTE: In contrast to xmlNodeSetContent(), @content is supposed to be  | 
5977  |  |  *       raw text, so unescaped XML special chars are allowed, entity  | 
5978  |  |  *       references are not supported.  | 
5979  |  |  */  | 
5980  |  | void  | 
5981  | 0  | xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) { | 
5982  | 0  |     int len;  | 
5983  |  | 
  | 
5984  | 0  |     if (cur == NULL) { | 
5985  |  | #ifdef DEBUG_TREE  | 
5986  |  |         xmlGenericError(xmlGenericErrorContext,  | 
5987  |  |     "xmlNodeAddContent : node == NULL\n");  | 
5988  |  | #endif  | 
5989  | 0  |   return;  | 
5990  | 0  |     }  | 
5991  | 0  |     if (content == NULL) return;  | 
5992  | 0  |     len = xmlStrlen(content);  | 
5993  | 0  |     xmlNodeAddContentLen(cur, content, len);  | 
5994  | 0  | }  | 
5995  |  |  | 
5996  |  | /**  | 
5997  |  |  * xmlTextMerge:  | 
5998  |  |  * @first:  the first text node  | 
5999  |  |  * @second:  the second text node being merged  | 
6000  |  |  *  | 
6001  |  |  * Merge two text nodes into one  | 
6002  |  |  * Returns the first text node augmented  | 
6003  |  |  */  | 
6004  |  | xmlNodePtr  | 
6005  | 0  | xmlTextMerge(xmlNodePtr first, xmlNodePtr second) { | 
6006  | 0  |     if (first == NULL) return(second);  | 
6007  | 0  |     if (second == NULL) return(first);  | 
6008  | 0  |     if (first->type != XML_TEXT_NODE) return(first);  | 
6009  | 0  |     if (second->type != XML_TEXT_NODE) return(first);  | 
6010  | 0  |     if (second->name != first->name)  | 
6011  | 0  |   return(first);  | 
6012  | 0  |     xmlNodeAddContent(first, second->content);  | 
6013  | 0  |     xmlUnlinkNode(second);  | 
6014  | 0  |     xmlFreeNode(second);  | 
6015  | 0  |     return(first);  | 
6016  | 0  | }  | 
6017  |  |  | 
6018  |  | #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)  | 
6019  |  | /**  | 
6020  |  |  * xmlGetNsList:  | 
6021  |  |  * @doc:  the document  | 
6022  |  |  * @node:  the current node  | 
6023  |  |  *  | 
6024  |  |  * Search all the namespace applying to a given element.  | 
6025  |  |  * Returns an NULL terminated array of all the #xmlNsPtr found  | 
6026  |  |  *         that need to be freed by the caller or NULL if no  | 
6027  |  |  *         namespace if defined  | 
6028  |  |  */  | 
6029  |  | xmlNsPtr *  | 
6030  |  | xmlGetNsList(const xmlDoc *doc ATTRIBUTE_UNUSED, const xmlNode *node)  | 
6031  | 1.65M  | { | 
6032  | 1.65M  |     xmlNsPtr cur;  | 
6033  | 1.65M  |     xmlNsPtr *ret = NULL;  | 
6034  | 1.65M  |     int nbns = 0;  | 
6035  | 1.65M  |     int maxns = 10;  | 
6036  | 1.65M  |     int i;  | 
6037  |  |  | 
6038  | 1.65M  |     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))  | 
6039  | 0  |         return(NULL);  | 
6040  |  |  | 
6041  | 6.96M  |     while (node != NULL) { | 
6042  | 5.30M  |         if (node->type == XML_ELEMENT_NODE) { | 
6043  | 3.65M  |             cur = node->nsDef;  | 
6044  | 6.21M  |             while (cur != NULL) { | 
6045  | 2.56M  |                 if (ret == NULL) { | 
6046  | 1.48M  |                     ret =  | 
6047  | 1.48M  |                         (xmlNsPtr *) xmlMalloc((maxns + 1) *  | 
6048  | 1.48M  |                                                sizeof(xmlNsPtr));  | 
6049  | 1.48M  |                     if (ret == NULL) { | 
6050  | 0  |       xmlTreeErrMemory("getting namespace list"); | 
6051  | 0  |                         return (NULL);  | 
6052  | 0  |                     }  | 
6053  | 1.48M  |                     ret[nbns] = NULL;  | 
6054  | 1.48M  |                 }  | 
6055  | 3.64M  |                 for (i = 0; i < nbns; i++) { | 
6056  | 1.07M  |                     if ((cur->prefix == ret[i]->prefix) ||  | 
6057  | 1.07M  |                         (xmlStrEqual(cur->prefix, ret[i]->prefix)))  | 
6058  | 0  |                         break;  | 
6059  | 1.07M  |                 }  | 
6060  | 2.56M  |                 if (i >= nbns) { | 
6061  | 2.56M  |                     if (nbns >= maxns) { | 
6062  | 0  |                         maxns *= 2;  | 
6063  | 0  |                         ret = (xmlNsPtr *) xmlRealloc(ret,  | 
6064  | 0  |                                                       (maxns +  | 
6065  | 0  |                                                        1) *  | 
6066  | 0  |                                                       sizeof(xmlNsPtr));  | 
6067  | 0  |                         if (ret == NULL) { | 
6068  | 0  |           xmlTreeErrMemory("getting namespace list"); | 
6069  | 0  |                             return (NULL);  | 
6070  | 0  |                         }  | 
6071  | 0  |                     }  | 
6072  | 2.56M  |                     ret[nbns++] = cur;  | 
6073  | 2.56M  |                     ret[nbns] = NULL;  | 
6074  | 2.56M  |                 }  | 
6075  |  |  | 
6076  | 2.56M  |                 cur = cur->next;  | 
6077  | 2.56M  |             }  | 
6078  | 3.65M  |         }  | 
6079  | 5.30M  |         node = node->parent;  | 
6080  | 5.30M  |     }  | 
6081  | 1.65M  |     return (ret);  | 
6082  | 1.65M  | }  | 
6083  |  | #endif /* LIBXML_TREE_ENABLED */  | 
6084  |  |  | 
6085  |  | /*  | 
6086  |  | * xmlTreeEnsureXMLDecl:  | 
6087  |  | * @doc: the doc  | 
6088  |  | *  | 
6089  |  | * Ensures that there is an XML namespace declaration on the doc.  | 
6090  |  | *  | 
6091  |  | * Returns the XML ns-struct or NULL on API and internal errors.  | 
6092  |  | */  | 
6093  |  | static xmlNsPtr  | 
6094  |  | xmlTreeEnsureXMLDecl(xmlDocPtr doc)  | 
6095  | 0  | { | 
6096  | 0  |     if (doc == NULL)  | 
6097  | 0  |   return (NULL);  | 
6098  | 0  |     if (doc->oldNs != NULL)  | 
6099  | 0  |   return (doc->oldNs);  | 
6100  | 0  |     { | 
6101  | 0  |   xmlNsPtr ns;  | 
6102  | 0  |   ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));  | 
6103  | 0  |   if (ns == NULL) { | 
6104  | 0  |       xmlTreeErrMemory(  | 
6105  | 0  |     "allocating the XML namespace");  | 
6106  | 0  |       return (NULL);  | 
6107  | 0  |   }  | 
6108  | 0  |   memset(ns, 0, sizeof(xmlNs));  | 
6109  | 0  |   ns->type = XML_LOCAL_NAMESPACE;  | 
6110  | 0  |   ns->href = xmlStrdup(XML_XML_NAMESPACE);  | 
6111  | 0  |   ns->prefix = xmlStrdup((const xmlChar *)"xml");  | 
6112  | 0  |   doc->oldNs = ns;  | 
6113  | 0  |   return (ns);  | 
6114  | 0  |     }  | 
6115  | 0  | }  | 
6116  |  |  | 
6117  |  | /**  | 
6118  |  |  * xmlSearchNs:  | 
6119  |  |  * @doc:  the document  | 
6120  |  |  * @node:  the current node  | 
6121  |  |  * @nameSpace:  the namespace prefix  | 
6122  |  |  *  | 
6123  |  |  * Search a Ns registered under a given name space for a document.  | 
6124  |  |  * recurse on the parents until it finds the defined namespace  | 
6125  |  |  * or return NULL otherwise.  | 
6126  |  |  * @nameSpace can be NULL, this is a search for the default namespace.  | 
6127  |  |  * We don't allow to cross entities boundaries. If you don't declare  | 
6128  |  |  * the namespace within those you will be in troubles !!! A warning  | 
6129  |  |  * is generated to cover this case.  | 
6130  |  |  *  | 
6131  |  |  * Returns the namespace pointer or NULL.  | 
6132  |  |  */  | 
6133  |  | xmlNsPtr  | 
6134  | 157k  | xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) { | 
6135  |  |  | 
6136  | 157k  |     xmlNsPtr cur;  | 
6137  | 157k  |     const xmlNode *orig = node;  | 
6138  |  |  | 
6139  | 157k  |     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL)) return(NULL);  | 
6140  | 157k  |     if ((nameSpace != NULL) &&  | 
6141  | 157k  |   (xmlStrEqual(nameSpace, (const xmlChar *)"xml"))) { | 
6142  | 0  |   if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) { | 
6143  |  |       /*  | 
6144  |  |        * The XML-1.0 namespace is normally held on the root  | 
6145  |  |        * element. In this case exceptionally create it on the  | 
6146  |  |        * node element.  | 
6147  |  |        */  | 
6148  | 0  |       cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));  | 
6149  | 0  |       if (cur == NULL) { | 
6150  | 0  |     xmlTreeErrMemory("searching namespace"); | 
6151  | 0  |     return(NULL);  | 
6152  | 0  |       }  | 
6153  | 0  |       memset(cur, 0, sizeof(xmlNs));  | 
6154  | 0  |       cur->type = XML_LOCAL_NAMESPACE;  | 
6155  | 0  |       cur->href = xmlStrdup(XML_XML_NAMESPACE);  | 
6156  | 0  |       cur->prefix = xmlStrdup((const xmlChar *)"xml");  | 
6157  | 0  |       cur->next = node->nsDef;  | 
6158  | 0  |       node->nsDef = cur;  | 
6159  | 0  |       return(cur);  | 
6160  | 0  |   }  | 
6161  | 0  |   if (doc == NULL) { | 
6162  | 0  |       doc = node->doc;  | 
6163  | 0  |       if (doc == NULL)  | 
6164  | 0  |     return(NULL);  | 
6165  | 0  |   }  | 
6166  |  |   /*  | 
6167  |  |   * Return the XML namespace declaration held by the doc.  | 
6168  |  |   */  | 
6169  | 0  |   if (doc->oldNs == NULL)  | 
6170  | 0  |       return(xmlTreeEnsureXMLDecl(doc));  | 
6171  | 0  |   else  | 
6172  | 0  |       return(doc->oldNs);  | 
6173  | 0  |     }  | 
6174  | 429k  |     while (node != NULL) { | 
6175  | 297k  |   if ((node->type == XML_ENTITY_REF_NODE) ||  | 
6176  | 297k  |       (node->type == XML_ENTITY_NODE) ||  | 
6177  | 297k  |       (node->type == XML_ENTITY_DECL))  | 
6178  | 0  |       return(NULL);  | 
6179  | 297k  |   if (node->type == XML_ELEMENT_NODE) { | 
6180  | 165k  |       cur = node->nsDef;  | 
6181  | 304k  |       while (cur != NULL) { | 
6182  | 165k  |     if ((cur->prefix == NULL) && (nameSpace == NULL) &&  | 
6183  | 165k  |         (cur->href != NULL))  | 
6184  | 0  |         return(cur);  | 
6185  | 165k  |     if ((cur->prefix != NULL) && (nameSpace != NULL) &&  | 
6186  | 165k  |         (cur->href != NULL) &&  | 
6187  | 165k  |         (xmlStrEqual(cur->prefix, nameSpace)))  | 
6188  | 25.9k  |         return(cur);  | 
6189  | 139k  |     cur = cur->next;  | 
6190  | 139k  |       }  | 
6191  | 139k  |       if (orig != node) { | 
6192  | 0  |           cur = node->ns;  | 
6193  | 0  |           if (cur != NULL) { | 
6194  | 0  |         if ((cur->prefix == NULL) && (nameSpace == NULL) &&  | 
6195  | 0  |             (cur->href != NULL))  | 
6196  | 0  |             return(cur);  | 
6197  | 0  |         if ((cur->prefix != NULL) && (nameSpace != NULL) &&  | 
6198  | 0  |             (cur->href != NULL) &&  | 
6199  | 0  |             (xmlStrEqual(cur->prefix, nameSpace)))  | 
6200  | 0  |             return(cur);  | 
6201  | 0  |           }  | 
6202  | 0  |       }  | 
6203  | 139k  |   }  | 
6204  | 271k  |   node = node->parent;  | 
6205  | 271k  |     }  | 
6206  | 131k  |     return(NULL);  | 
6207  | 157k  | }  | 
6208  |  |  | 
6209  |  | /**  | 
6210  |  |  * xmlNsInScope:  | 
6211  |  |  * @doc:  the document  | 
6212  |  |  * @node:  the current node  | 
6213  |  |  * @ancestor:  the ancestor carrying the namespace  | 
6214  |  |  * @prefix:  the namespace prefix  | 
6215  |  |  *  | 
6216  |  |  * Verify that the given namespace held on @ancestor is still in scope  | 
6217  |  |  * on node.  | 
6218  |  |  *  | 
6219  |  |  * Returns 1 if true, 0 if false and -1 in case of error.  | 
6220  |  |  */  | 
6221  |  | static int  | 
6222  |  | xmlNsInScope(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node,  | 
6223  |  |              xmlNodePtr ancestor, const xmlChar * prefix)  | 
6224  | 0  | { | 
6225  | 0  |     xmlNsPtr tst;  | 
6226  |  | 
  | 
6227  | 0  |     while ((node != NULL) && (node != ancestor)) { | 
6228  | 0  |         if ((node->type == XML_ENTITY_REF_NODE) ||  | 
6229  | 0  |             (node->type == XML_ENTITY_NODE) ||  | 
6230  | 0  |             (node->type == XML_ENTITY_DECL))  | 
6231  | 0  |             return (-1);  | 
6232  | 0  |         if (node->type == XML_ELEMENT_NODE) { | 
6233  | 0  |             tst = node->nsDef;  | 
6234  | 0  |             while (tst != NULL) { | 
6235  | 0  |                 if ((tst->prefix == NULL)  | 
6236  | 0  |                     && (prefix == NULL))  | 
6237  | 0  |                     return (0);  | 
6238  | 0  |                 if ((tst->prefix != NULL)  | 
6239  | 0  |                     && (prefix != NULL)  | 
6240  | 0  |                     && (xmlStrEqual(tst->prefix, prefix)))  | 
6241  | 0  |                     return (0);  | 
6242  | 0  |                 tst = tst->next;  | 
6243  | 0  |             }  | 
6244  | 0  |         }  | 
6245  | 0  |         node = node->parent;  | 
6246  | 0  |     }  | 
6247  | 0  |     if (node != ancestor)  | 
6248  | 0  |         return (-1);  | 
6249  | 0  |     return (1);  | 
6250  | 0  | }  | 
6251  |  |  | 
6252  |  | /**  | 
6253  |  |  * xmlSearchNsByHref:  | 
6254  |  |  * @doc:  the document  | 
6255  |  |  * @node:  the current node  | 
6256  |  |  * @href:  the namespace value  | 
6257  |  |  *  | 
6258  |  |  * Search a Ns aliasing a given URI. Recurse on the parents until it finds  | 
6259  |  |  * the defined namespace or return NULL otherwise.  | 
6260  |  |  * Returns the namespace pointer or NULL.  | 
6261  |  |  */  | 
6262  |  | xmlNsPtr  | 
6263  |  | xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href)  | 
6264  | 0  | { | 
6265  | 0  |     xmlNsPtr cur;  | 
6266  | 0  |     xmlNodePtr orig = node;  | 
6267  | 0  |     int is_attr;  | 
6268  |  | 
  | 
6269  | 0  |     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) || (href == NULL))  | 
6270  | 0  |         return (NULL);  | 
6271  | 0  |     if (xmlStrEqual(href, XML_XML_NAMESPACE)) { | 
6272  |  |         /*  | 
6273  |  |          * Only the document can hold the XML spec namespace.  | 
6274  |  |          */  | 
6275  | 0  |         if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) { | 
6276  |  |             /*  | 
6277  |  |              * The XML-1.0 namespace is normally held on the root  | 
6278  |  |              * element. In this case exceptionally create it on the  | 
6279  |  |              * node element.  | 
6280  |  |              */  | 
6281  | 0  |             cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));  | 
6282  | 0  |             if (cur == NULL) { | 
6283  | 0  |     xmlTreeErrMemory("searching namespace"); | 
6284  | 0  |                 return (NULL);  | 
6285  | 0  |             }  | 
6286  | 0  |             memset(cur, 0, sizeof(xmlNs));  | 
6287  | 0  |             cur->type = XML_LOCAL_NAMESPACE;  | 
6288  | 0  |             cur->href = xmlStrdup(XML_XML_NAMESPACE);  | 
6289  | 0  |             cur->prefix = xmlStrdup((const xmlChar *) "xml");  | 
6290  | 0  |             cur->next = node->nsDef;  | 
6291  | 0  |             node->nsDef = cur;  | 
6292  | 0  |             return (cur);  | 
6293  | 0  |         }  | 
6294  | 0  |   if (doc == NULL) { | 
6295  | 0  |       doc = node->doc;  | 
6296  | 0  |       if (doc == NULL)  | 
6297  | 0  |     return(NULL);  | 
6298  | 0  |   }  | 
6299  |  |   /*  | 
6300  |  |   * Return the XML namespace declaration held by the doc.  | 
6301  |  |   */  | 
6302  | 0  |   if (doc->oldNs == NULL)  | 
6303  | 0  |       return(xmlTreeEnsureXMLDecl(doc));  | 
6304  | 0  |   else  | 
6305  | 0  |       return(doc->oldNs);  | 
6306  | 0  |     }  | 
6307  | 0  |     is_attr = (node->type == XML_ATTRIBUTE_NODE);  | 
6308  | 0  |     while (node != NULL) { | 
6309  | 0  |         if ((node->type == XML_ENTITY_REF_NODE) ||  | 
6310  | 0  |             (node->type == XML_ENTITY_NODE) ||  | 
6311  | 0  |             (node->type == XML_ENTITY_DECL))  | 
6312  | 0  |             return (NULL);  | 
6313  | 0  |         if (node->type == XML_ELEMENT_NODE) { | 
6314  | 0  |             cur = node->nsDef;  | 
6315  | 0  |             while (cur != NULL) { | 
6316  | 0  |                 if ((cur->href != NULL) && (href != NULL) &&  | 
6317  | 0  |                     (xmlStrEqual(cur->href, href))) { | 
6318  | 0  |         if (((!is_attr) || (cur->prefix != NULL)) &&  | 
6319  | 0  |             (xmlNsInScope(doc, orig, node, cur->prefix) == 1))  | 
6320  | 0  |       return (cur);  | 
6321  | 0  |                 }  | 
6322  | 0  |                 cur = cur->next;  | 
6323  | 0  |             }  | 
6324  | 0  |             if (orig != node) { | 
6325  | 0  |                 cur = node->ns;  | 
6326  | 0  |                 if (cur != NULL) { | 
6327  | 0  |                     if ((cur->href != NULL) && (href != NULL) &&  | 
6328  | 0  |                         (xmlStrEqual(cur->href, href))) { | 
6329  | 0  |       if (((!is_attr) || (cur->prefix != NULL)) &&  | 
6330  | 0  |                 (xmlNsInScope(doc, orig, node, cur->prefix) == 1))  | 
6331  | 0  |           return (cur);  | 
6332  | 0  |                     }  | 
6333  | 0  |                 }  | 
6334  | 0  |             }  | 
6335  | 0  |         }  | 
6336  | 0  |         node = node->parent;  | 
6337  | 0  |     }  | 
6338  | 0  |     return (NULL);  | 
6339  | 0  | }  | 
6340  |  |  | 
6341  |  | /**  | 
6342  |  |  * xmlNewReconciledNs:  | 
6343  |  |  * @doc:  the document  | 
6344  |  |  * @tree:  a node expected to hold the new namespace  | 
6345  |  |  * @ns:  the original namespace  | 
6346  |  |  *  | 
6347  |  |  * This function tries to locate a namespace definition in a tree  | 
6348  |  |  * ancestors, or create a new namespace definition node similar to  | 
6349  |  |  * @ns trying to reuse the same prefix. However if the given prefix is  | 
6350  |  |  * null (default namespace) or reused within the subtree defined by  | 
6351  |  |  * @tree or on one of its ancestors then a new prefix is generated.  | 
6352  |  |  * Returns the (new) namespace definition or NULL in case of error  | 
6353  |  |  */  | 
6354  |  | static xmlNsPtr  | 
6355  | 0  | xmlNewReconciledNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) { | 
6356  | 0  |     xmlNsPtr def;  | 
6357  | 0  |     xmlChar prefix[50];  | 
6358  | 0  |     int counter = 1;  | 
6359  |  | 
  | 
6360  | 0  |     if ((tree == NULL) || (tree->type != XML_ELEMENT_NODE)) { | 
6361  |  | #ifdef DEBUG_TREE  | 
6362  |  |         xmlGenericError(xmlGenericErrorContext,  | 
6363  |  |     "xmlNewReconciledNs : tree == NULL\n");  | 
6364  |  | #endif  | 
6365  | 0  |   return(NULL);  | 
6366  | 0  |     }  | 
6367  | 0  |     if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) { | 
6368  |  | #ifdef DEBUG_TREE  | 
6369  |  |         xmlGenericError(xmlGenericErrorContext,  | 
6370  |  |     "xmlNewReconciledNs : ns == NULL\n");  | 
6371  |  | #endif  | 
6372  | 0  |   return(NULL);  | 
6373  | 0  |     }  | 
6374  |  |     /*  | 
6375  |  |      * Search an existing namespace definition inherited.  | 
6376  |  |      */  | 
6377  | 0  |     def = xmlSearchNsByHref(doc, tree, ns->href);  | 
6378  | 0  |     if (def != NULL)  | 
6379  | 0  |         return(def);  | 
6380  |  |  | 
6381  |  |     /*  | 
6382  |  |      * Find a close prefix which is not already in use.  | 
6383  |  |      * Let's strip namespace prefixes longer than 20 chars !  | 
6384  |  |      */  | 
6385  | 0  |     if (ns->prefix == NULL)  | 
6386  | 0  |   snprintf((char *) prefix, sizeof(prefix), "default");  | 
6387  | 0  |     else  | 
6388  | 0  |   snprintf((char *) prefix, sizeof(prefix), "%.20s", (char *)ns->prefix);  | 
6389  |  | 
  | 
6390  | 0  |     def = xmlSearchNs(doc, tree, prefix);  | 
6391  | 0  |     while (def != NULL) { | 
6392  | 0  |         if (counter > 1000) return(NULL);  | 
6393  | 0  |   if (ns->prefix == NULL)  | 
6394  | 0  |       snprintf((char *) prefix, sizeof(prefix), "default%d", counter++);  | 
6395  | 0  |   else  | 
6396  | 0  |       snprintf((char *) prefix, sizeof(prefix), "%.20s%d",  | 
6397  | 0  |     (char *)ns->prefix, counter++);  | 
6398  | 0  |   def = xmlSearchNs(doc, tree, prefix);  | 
6399  | 0  |     }  | 
6400  |  |  | 
6401  |  |     /*  | 
6402  |  |      * OK, now we are ready to create a new one.  | 
6403  |  |      */  | 
6404  | 0  |     def = xmlNewNs(tree, ns->href, prefix);  | 
6405  | 0  |     return(def);  | 
6406  | 0  | }  | 
6407  |  |  | 
6408  |  | #ifdef LIBXML_TREE_ENABLED  | 
6409  |  | /**  | 
6410  |  |  * xmlReconciliateNs:  | 
6411  |  |  * @doc:  the document  | 
6412  |  |  * @tree:  a node defining the subtree to reconciliate  | 
6413  |  |  *  | 
6414  |  |  * This function checks that all the namespaces declared within the given  | 
6415  |  |  * tree are properly declared. This is needed for example after Copy or Cut  | 
6416  |  |  * and then paste operations. The subtree may still hold pointers to  | 
6417  |  |  * namespace declarations outside the subtree or invalid/masked. As much  | 
6418  |  |  * as possible the function try to reuse the existing namespaces found in  | 
6419  |  |  * the new environment. If not possible the new namespaces are redeclared  | 
6420  |  |  * on @tree at the top of the given subtree.  | 
6421  |  |  * Returns the number of namespace declarations created or -1 in case of error.  | 
6422  |  |  */  | 
6423  |  | int  | 
6424  | 0  | xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { | 
6425  | 0  |     xmlNsPtr *oldNs = NULL;  | 
6426  | 0  |     xmlNsPtr *newNs = NULL;  | 
6427  | 0  |     int sizeCache = 0;  | 
6428  | 0  |     int nbCache = 0;  | 
6429  |  | 
  | 
6430  | 0  |     xmlNsPtr n;  | 
6431  | 0  |     xmlNodePtr node = tree;  | 
6432  | 0  |     xmlAttrPtr attr;  | 
6433  | 0  |     int ret = 0, i;  | 
6434  |  | 
  | 
6435  | 0  |     if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) return(-1);  | 
6436  | 0  |     if ((doc == NULL) || (doc->type != XML_DOCUMENT_NODE)) return(-1);  | 
6437  | 0  |     if (node->doc != doc) return(-1);  | 
6438  | 0  |     while (node != NULL) { | 
6439  |  |         /*  | 
6440  |  |    * Reconciliate the node namespace  | 
6441  |  |    */  | 
6442  | 0  |   if (node->ns != NULL) { | 
6443  |  |       /*  | 
6444  |  |        * initialize the cache if needed  | 
6445  |  |        */  | 
6446  | 0  |       if (sizeCache == 0) { | 
6447  | 0  |     sizeCache = 10;  | 
6448  | 0  |     oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *  | 
6449  | 0  |                  sizeof(xmlNsPtr));  | 
6450  | 0  |     if (oldNs == NULL) { | 
6451  | 0  |         xmlTreeErrMemory("fixing namespaces"); | 
6452  | 0  |         return(-1);  | 
6453  | 0  |     }  | 
6454  | 0  |     newNs = (xmlNsPtr *) xmlMalloc(sizeCache *  | 
6455  | 0  |                  sizeof(xmlNsPtr));  | 
6456  | 0  |     if (newNs == NULL) { | 
6457  | 0  |         xmlTreeErrMemory("fixing namespaces"); | 
6458  | 0  |         xmlFree(oldNs);  | 
6459  | 0  |         return(-1);  | 
6460  | 0  |     }  | 
6461  | 0  |       }  | 
6462  | 0  |       for (i = 0;i < nbCache;i++) { | 
6463  | 0  |           if (oldNs[i] == node->ns) { | 
6464  | 0  |         node->ns = newNs[i];  | 
6465  | 0  |         break;  | 
6466  | 0  |     }  | 
6467  | 0  |       }  | 
6468  | 0  |       if (i == nbCache) { | 
6469  |  |           /*  | 
6470  |  |      * OK we need to recreate a new namespace definition  | 
6471  |  |      */  | 
6472  | 0  |     n = xmlNewReconciledNs(doc, tree, node->ns);  | 
6473  | 0  |     if (n != NULL) { /* :-( what if else ??? */ | 
6474  |  |         /*  | 
6475  |  |          * check if we need to grow the cache buffers.  | 
6476  |  |          */  | 
6477  | 0  |         if (sizeCache <= nbCache) { | 
6478  | 0  |             sizeCache *= 2;  | 
6479  | 0  |       oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *  | 
6480  | 0  |                                      sizeof(xmlNsPtr));  | 
6481  | 0  |             if (oldNs == NULL) { | 
6482  | 0  |           xmlTreeErrMemory("fixing namespaces"); | 
6483  | 0  |           xmlFree(newNs);  | 
6484  | 0  |           return(-1);  | 
6485  | 0  |       }  | 
6486  | 0  |       newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *  | 
6487  | 0  |                                      sizeof(xmlNsPtr));  | 
6488  | 0  |             if (newNs == NULL) { | 
6489  | 0  |           xmlTreeErrMemory("fixing namespaces"); | 
6490  | 0  |           xmlFree(oldNs);  | 
6491  | 0  |           return(-1);  | 
6492  | 0  |       }  | 
6493  | 0  |         }  | 
6494  | 0  |         newNs[nbCache] = n;  | 
6495  | 0  |         oldNs[nbCache++] = node->ns;  | 
6496  | 0  |         node->ns = n;  | 
6497  | 0  |                 }  | 
6498  | 0  |       }  | 
6499  | 0  |   }  | 
6500  |  |   /*  | 
6501  |  |    * now check for namespace held by attributes on the node.  | 
6502  |  |    */  | 
6503  | 0  |   if (node->type == XML_ELEMENT_NODE) { | 
6504  | 0  |       attr = node->properties;  | 
6505  | 0  |       while (attr != NULL) { | 
6506  | 0  |     if (attr->ns != NULL) { | 
6507  |  |         /*  | 
6508  |  |          * initialize the cache if needed  | 
6509  |  |          */  | 
6510  | 0  |         if (sizeCache == 0) { | 
6511  | 0  |       sizeCache = 10;  | 
6512  | 0  |       oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *  | 
6513  | 0  |                    sizeof(xmlNsPtr));  | 
6514  | 0  |       if (oldNs == NULL) { | 
6515  | 0  |           xmlTreeErrMemory("fixing namespaces"); | 
6516  | 0  |           return(-1);  | 
6517  | 0  |       }  | 
6518  | 0  |       newNs = (xmlNsPtr *) xmlMalloc(sizeCache *  | 
6519  | 0  |                    sizeof(xmlNsPtr));  | 
6520  | 0  |       if (newNs == NULL) { | 
6521  | 0  |           xmlTreeErrMemory("fixing namespaces"); | 
6522  | 0  |           xmlFree(oldNs);  | 
6523  | 0  |           return(-1);  | 
6524  | 0  |       }  | 
6525  | 0  |         }  | 
6526  | 0  |         for (i = 0;i < nbCache;i++) { | 
6527  | 0  |       if (oldNs[i] == attr->ns) { | 
6528  | 0  |           attr->ns = newNs[i];  | 
6529  | 0  |           break;  | 
6530  | 0  |       }  | 
6531  | 0  |         }  | 
6532  | 0  |         if (i == nbCache) { | 
6533  |  |       /*  | 
6534  |  |        * OK we need to recreate a new namespace definition  | 
6535  |  |        */  | 
6536  | 0  |       n = xmlNewReconciledNs(doc, tree, attr->ns);  | 
6537  | 0  |       if (n != NULL) { /* :-( what if else ??? */ | 
6538  |  |           /*  | 
6539  |  |            * check if we need to grow the cache buffers.  | 
6540  |  |            */  | 
6541  | 0  |           if (sizeCache <= nbCache) { | 
6542  | 0  |         sizeCache *= 2;  | 
6543  | 0  |         oldNs = (xmlNsPtr *) xmlRealloc(oldNs,  | 
6544  | 0  |                    sizeCache * sizeof(xmlNsPtr));  | 
6545  | 0  |         if (oldNs == NULL) { | 
6546  | 0  |             xmlTreeErrMemory("fixing namespaces"); | 
6547  | 0  |             xmlFree(newNs);  | 
6548  | 0  |             return(-1);  | 
6549  | 0  |         }  | 
6550  | 0  |         newNs = (xmlNsPtr *) xmlRealloc(newNs,  | 
6551  | 0  |                    sizeCache * sizeof(xmlNsPtr));  | 
6552  | 0  |         if (newNs == NULL) { | 
6553  | 0  |             xmlTreeErrMemory("fixing namespaces"); | 
6554  | 0  |             xmlFree(oldNs);  | 
6555  | 0  |             return(-1);  | 
6556  | 0  |         }  | 
6557  | 0  |           }  | 
6558  | 0  |           newNs[nbCache] = n;  | 
6559  | 0  |           oldNs[nbCache++] = attr->ns;  | 
6560  | 0  |           attr->ns = n;  | 
6561  | 0  |       }  | 
6562  | 0  |         }  | 
6563  | 0  |     }  | 
6564  | 0  |     attr = attr->next;  | 
6565  | 0  |       }  | 
6566  | 0  |   }  | 
6567  |  |  | 
6568  |  |   /*  | 
6569  |  |    * Browse the full subtree, deep first  | 
6570  |  |    */  | 
6571  | 0  |         if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) { | 
6572  |  |       /* deep first */  | 
6573  | 0  |       node = node->children;  | 
6574  | 0  |   } else if ((node != tree) && (node->next != NULL)) { | 
6575  |  |       /* then siblings */  | 
6576  | 0  |       node = node->next;  | 
6577  | 0  |   } else if (node != tree) { | 
6578  |  |       /* go up to parents->next if needed */  | 
6579  | 0  |       while (node != tree) { | 
6580  | 0  |           if (node->parent != NULL)  | 
6581  | 0  |         node = node->parent;  | 
6582  | 0  |     if ((node != tree) && (node->next != NULL)) { | 
6583  | 0  |         node = node->next;  | 
6584  | 0  |         break;  | 
6585  | 0  |     }  | 
6586  | 0  |     if (node->parent == NULL) { | 
6587  | 0  |         node = NULL;  | 
6588  | 0  |         break;  | 
6589  | 0  |     }  | 
6590  | 0  |       }  | 
6591  |  |       /* exit condition */  | 
6592  | 0  |       if (node == tree)  | 
6593  | 0  |           node = NULL;  | 
6594  | 0  |   } else  | 
6595  | 0  |       break;  | 
6596  | 0  |     }  | 
6597  | 0  |     if (oldNs != NULL)  | 
6598  | 0  |   xmlFree(oldNs);  | 
6599  | 0  |     if (newNs != NULL)  | 
6600  | 0  |   xmlFree(newNs);  | 
6601  | 0  |     return(ret);  | 
6602  | 0  | }  | 
6603  |  | #endif /* LIBXML_TREE_ENABLED */  | 
6604  |  |  | 
6605  |  | static xmlAttrPtr  | 
6606  |  | xmlGetPropNodeInternal(const xmlNode *node, const xmlChar *name,  | 
6607  |  |            const xmlChar *nsName, int useDTD)  | 
6608  | 3.73M  | { | 
6609  | 3.73M  |     xmlAttrPtr prop;  | 
6610  |  |  | 
6611  |  |     /* Avoid unused variable warning if features are disabled. */  | 
6612  | 3.73M  |     (void) useDTD;  | 
6613  |  |  | 
6614  | 3.73M  |     if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))  | 
6615  | 54.1k  |   return(NULL);  | 
6616  |  |  | 
6617  | 3.67M  |     if (node->properties != NULL) { | 
6618  | 145k  |   prop = node->properties;  | 
6619  | 145k  |   if (nsName == NULL) { | 
6620  |  |       /*  | 
6621  |  |       * We want the attr to be in no namespace.  | 
6622  |  |       */  | 
6623  | 0  |       do { | 
6624  | 0  |     if ((prop->ns == NULL) && xmlStrEqual(prop->name, name)) { | 
6625  | 0  |         return(prop);  | 
6626  | 0  |     }  | 
6627  | 0  |     prop = prop->next;  | 
6628  | 0  |       } while (prop != NULL);  | 
6629  | 145k  |   } else { | 
6630  |  |       /*  | 
6631  |  |       * We want the attr to be in the specified namespace.  | 
6632  |  |       */  | 
6633  | 208k  |       do { | 
6634  | 208k  |     if ((prop->ns != NULL) && xmlStrEqual(prop->name, name) &&  | 
6635  | 208k  |         ((prop->ns->href == nsName) ||  | 
6636  | 0  |          xmlStrEqual(prop->ns->href, nsName)))  | 
6637  | 0  |     { | 
6638  | 0  |         return(prop);  | 
6639  | 0  |     }  | 
6640  | 208k  |     prop = prop->next;  | 
6641  | 208k  |       } while (prop != NULL);  | 
6642  | 145k  |   }  | 
6643  | 145k  |     }  | 
6644  |  |  | 
6645  | 3.67M  | #ifdef LIBXML_TREE_ENABLED  | 
6646  | 3.67M  |     if (! useDTD)  | 
6647  | 0  |   return(NULL);  | 
6648  |  |     /*  | 
6649  |  |      * Check if there is a default/fixed attribute declaration in  | 
6650  |  |      * the internal or external subset.  | 
6651  |  |      */  | 
6652  | 3.67M  |     if ((node->doc != NULL) && (node->doc->intSubset != NULL)) { | 
6653  | 0  |   xmlDocPtr doc = node->doc;  | 
6654  | 0  |   xmlAttributePtr attrDecl = NULL;  | 
6655  | 0  |   xmlChar *elemQName, *tmpstr = NULL;  | 
6656  |  |  | 
6657  |  |   /*  | 
6658  |  |   * We need the QName of the element for the DTD-lookup.  | 
6659  |  |   */  | 
6660  | 0  |   if ((node->ns != NULL) && (node->ns->prefix != NULL)) { | 
6661  | 0  |       tmpstr = xmlStrdup(node->ns->prefix);  | 
6662  | 0  |       tmpstr = xmlStrcat(tmpstr, BAD_CAST ":");  | 
6663  | 0  |       tmpstr = xmlStrcat(tmpstr, node->name);  | 
6664  | 0  |       if (tmpstr == NULL)  | 
6665  | 0  |     return(NULL);  | 
6666  | 0  |       elemQName = tmpstr;  | 
6667  | 0  |   } else  | 
6668  | 0  |       elemQName = (xmlChar *) node->name;  | 
6669  | 0  |   if (nsName == NULL) { | 
6670  |  |       /*  | 
6671  |  |       * The common and nice case: Attr in no namespace.  | 
6672  |  |       */  | 
6673  | 0  |       attrDecl = xmlGetDtdQAttrDesc(doc->intSubset,  | 
6674  | 0  |     elemQName, name, NULL);  | 
6675  | 0  |       if ((attrDecl == NULL) && (doc->extSubset != NULL)) { | 
6676  | 0  |     attrDecl = xmlGetDtdQAttrDesc(doc->extSubset,  | 
6677  | 0  |         elemQName, name, NULL);  | 
6678  | 0  |       }  | 
6679  | 0  |         } else if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) { | 
6680  |  |       /*  | 
6681  |  |       * The XML namespace must be bound to prefix 'xml'.  | 
6682  |  |       */  | 
6683  | 0  |       attrDecl = xmlGetDtdQAttrDesc(doc->intSubset,  | 
6684  | 0  |     elemQName, name, BAD_CAST "xml");  | 
6685  | 0  |       if ((attrDecl == NULL) && (doc->extSubset != NULL)) { | 
6686  | 0  |     attrDecl = xmlGetDtdQAttrDesc(doc->extSubset,  | 
6687  | 0  |         elemQName, name, BAD_CAST "xml");  | 
6688  | 0  |       }  | 
6689  | 0  |   } else { | 
6690  | 0  |       xmlNsPtr *nsList, *cur;  | 
6691  |  |  | 
6692  |  |       /*  | 
6693  |  |       * The ugly case: Search using the prefixes of in-scope  | 
6694  |  |       * ns-decls corresponding to @nsName.  | 
6695  |  |       */  | 
6696  | 0  |       nsList = xmlGetNsList(node->doc, node);  | 
6697  | 0  |       if (nsList == NULL) { | 
6698  | 0  |     if (tmpstr != NULL)  | 
6699  | 0  |         xmlFree(tmpstr);  | 
6700  | 0  |     return(NULL);  | 
6701  | 0  |       }  | 
6702  | 0  |       cur = nsList;  | 
6703  | 0  |       while (*cur != NULL) { | 
6704  | 0  |     if (xmlStrEqual((*cur)->href, nsName)) { | 
6705  | 0  |         attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elemQName,  | 
6706  | 0  |       name, (*cur)->prefix);  | 
6707  | 0  |         if (attrDecl)  | 
6708  | 0  |       break;  | 
6709  | 0  |         if (doc->extSubset != NULL) { | 
6710  | 0  |       attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elemQName,  | 
6711  | 0  |           name, (*cur)->prefix);  | 
6712  | 0  |       if (attrDecl)  | 
6713  | 0  |           break;  | 
6714  | 0  |         }  | 
6715  | 0  |     }  | 
6716  | 0  |     cur++;  | 
6717  | 0  |       }  | 
6718  | 0  |       xmlFree(nsList);  | 
6719  | 0  |   }  | 
6720  | 0  |   if (tmpstr != NULL)  | 
6721  | 0  |       xmlFree(tmpstr);  | 
6722  |  |   /*  | 
6723  |  |   * Only default/fixed attrs are relevant.  | 
6724  |  |   */  | 
6725  | 0  |   if ((attrDecl != NULL) && (attrDecl->defaultValue != NULL))  | 
6726  | 0  |       return((xmlAttrPtr) attrDecl);  | 
6727  | 0  |     }  | 
6728  | 3.67M  | #endif /* LIBXML_TREE_ENABLED */  | 
6729  | 3.67M  |     return(NULL);  | 
6730  | 3.67M  | }  | 
6731  |  |  | 
6732  |  | static xmlChar*  | 
6733  |  | xmlGetPropNodeValueInternal(const xmlAttr *prop)  | 
6734  | 786k  | { | 
6735  | 786k  |     if (prop == NULL)  | 
6736  | 0  |   return(NULL);  | 
6737  | 786k  |     if (prop->type == XML_ATTRIBUTE_NODE) { | 
6738  |  |   /*  | 
6739  |  |   * Note that we return at least the empty string.  | 
6740  |  |   *   TODO: Do we really always want that?  | 
6741  |  |   */  | 
6742  | 786k  |   if (prop->children != NULL) { | 
6743  | 786k  |       if ((prop->children->next == NULL) &&  | 
6744  | 786k  |     ((prop->children->type == XML_TEXT_NODE) ||  | 
6745  | 786k  |     (prop->children->type == XML_CDATA_SECTION_NODE)))  | 
6746  | 786k  |       { | 
6747  |  |     /*  | 
6748  |  |     * Optimization for the common case: only 1 text node.  | 
6749  |  |     */  | 
6750  | 786k  |     return(xmlStrdup(prop->children->content));  | 
6751  | 786k  |       } else { | 
6752  | 0  |     xmlChar *ret;  | 
6753  |  | 
  | 
6754  | 0  |     ret = xmlNodeListGetString(prop->doc, prop->children, 1);  | 
6755  | 0  |     if (ret != NULL)  | 
6756  | 0  |         return(ret);  | 
6757  | 0  |       }  | 
6758  | 786k  |   }  | 
6759  | 0  |   return(xmlStrdup((xmlChar *)""));  | 
6760  | 786k  |     } else if (prop->type == XML_ATTRIBUTE_DECL) { | 
6761  | 0  |   return(xmlStrdup(((xmlAttributePtr)prop)->defaultValue));  | 
6762  | 0  |     }  | 
6763  | 0  |     return(NULL);  | 
6764  | 786k  | }  | 
6765  |  |  | 
6766  |  | /**  | 
6767  |  |  * xmlHasProp:  | 
6768  |  |  * @node:  the node  | 
6769  |  |  * @name:  the attribute name  | 
6770  |  |  *  | 
6771  |  |  * Search an attribute associated to a node  | 
6772  |  |  * This function also looks in DTD attribute declaration for #FIXED or  | 
6773  |  |  * default declaration values unless DTD use has been turned off.  | 
6774  |  |  *  | 
6775  |  |  * Returns the attribute or the attribute declaration or NULL if  | 
6776  |  |  *         neither was found.  | 
6777  |  |  */  | 
6778  |  | xmlAttrPtr  | 
6779  | 0  | xmlHasProp(const xmlNode *node, const xmlChar *name) { | 
6780  | 0  |     xmlAttrPtr prop;  | 
6781  | 0  |     xmlDocPtr doc;  | 
6782  |  | 
  | 
6783  | 0  |     if ((node == NULL) || (node->type != XML_ELEMENT_NODE) || (name == NULL))  | 
6784  | 0  |         return(NULL);  | 
6785  |  |     /*  | 
6786  |  |      * Check on the properties attached to the node  | 
6787  |  |      */  | 
6788  | 0  |     prop = node->properties;  | 
6789  | 0  |     while (prop != NULL) { | 
6790  | 0  |         if (xmlStrEqual(prop->name, name))  { | 
6791  | 0  |       return(prop);  | 
6792  | 0  |         }  | 
6793  | 0  |   prop = prop->next;  | 
6794  | 0  |     }  | 
6795  | 0  |     if (!xmlCheckDTD) return(NULL);  | 
6796  |  |  | 
6797  |  |     /*  | 
6798  |  |      * Check if there is a default declaration in the internal  | 
6799  |  |      * or external subsets  | 
6800  |  |      */  | 
6801  | 0  |     doc =  node->doc;  | 
6802  | 0  |     if (doc != NULL) { | 
6803  | 0  |         xmlAttributePtr attrDecl;  | 
6804  | 0  |         if (doc->intSubset != NULL) { | 
6805  | 0  |       attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);  | 
6806  | 0  |       if ((attrDecl == NULL) && (doc->extSubset != NULL))  | 
6807  | 0  |     attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);  | 
6808  | 0  |             if ((attrDecl != NULL) && (attrDecl->defaultValue != NULL))  | 
6809  |  |               /* return attribute declaration only if a default value is given  | 
6810  |  |                  (that includes #FIXED declarations) */  | 
6811  | 0  |     return((xmlAttrPtr) attrDecl);  | 
6812  | 0  |   }  | 
6813  | 0  |     }  | 
6814  | 0  |     return(NULL);  | 
6815  | 0  | }  | 
6816  |  |  | 
6817  |  | /**  | 
6818  |  |  * xmlHasNsProp:  | 
6819  |  |  * @node:  the node  | 
6820  |  |  * @name:  the attribute name  | 
6821  |  |  * @nameSpace:  the URI of the namespace  | 
6822  |  |  *  | 
6823  |  |  * Search for an attribute associated to a node  | 
6824  |  |  * This attribute has to be anchored in the namespace specified.  | 
6825  |  |  * This does the entity substitution.  | 
6826  |  |  * This function looks in DTD attribute declaration for #FIXED or  | 
6827  |  |  * default declaration values unless DTD use has been turned off.  | 
6828  |  |  * Note that a namespace of NULL indicates to use the default namespace.  | 
6829  |  |  *  | 
6830  |  |  * Returns the attribute or the attribute declaration or NULL  | 
6831  |  |  *     if neither was found.  | 
6832  |  |  */  | 
6833  |  | xmlAttrPtr  | 
6834  | 0  | xmlHasNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) { | 
6835  |  | 
  | 
6836  | 0  |     return(xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD));  | 
6837  | 0  | }  | 
6838  |  |  | 
6839  |  | /**  | 
6840  |  |  * xmlGetProp:  | 
6841  |  |  * @node:  the node  | 
6842  |  |  * @name:  the attribute name  | 
6843  |  |  *  | 
6844  |  |  * Search and get the value of an attribute associated to a node  | 
6845  |  |  * This does the entity substitution.  | 
6846  |  |  * This function looks in DTD attribute declaration for #FIXED or  | 
6847  |  |  * default declaration values unless DTD use has been turned off.  | 
6848  |  |  * NOTE: this function acts independently of namespaces associated  | 
6849  |  |  *       to the attribute. Use xmlGetNsProp() or xmlGetNoNsProp()  | 
6850  |  |  *       for namespace aware processing.  | 
6851  |  |  *  | 
6852  |  |  * Returns the attribute value or NULL if not found.  | 
6853  |  |  *     It's up to the caller to free the memory with xmlFree().  | 
6854  |  |  */  | 
6855  |  | xmlChar *  | 
6856  | 0  | xmlGetProp(const xmlNode *node, const xmlChar *name) { | 
6857  | 0  |     xmlAttrPtr prop;  | 
6858  |  | 
  | 
6859  | 0  |     prop = xmlHasProp(node, name);  | 
6860  | 0  |     if (prop == NULL)  | 
6861  | 0  |   return(NULL);  | 
6862  | 0  |     return(xmlGetPropNodeValueInternal(prop));  | 
6863  | 0  | }  | 
6864  |  |  | 
6865  |  | /**  | 
6866  |  |  * xmlGetNoNsProp:  | 
6867  |  |  * @node:  the node  | 
6868  |  |  * @name:  the attribute name  | 
6869  |  |  *  | 
6870  |  |  * Search and get the value of an attribute associated to a node  | 
6871  |  |  * This does the entity substitution.  | 
6872  |  |  * This function looks in DTD attribute declaration for #FIXED or  | 
6873  |  |  * default declaration values unless DTD use has been turned off.  | 
6874  |  |  * This function is similar to xmlGetProp except it will accept only  | 
6875  |  |  * an attribute in no namespace.  | 
6876  |  |  *  | 
6877  |  |  * Returns the attribute value or NULL if not found.  | 
6878  |  |  *     It's up to the caller to free the memory with xmlFree().  | 
6879  |  |  */  | 
6880  |  | xmlChar *  | 
6881  | 0  | xmlGetNoNsProp(const xmlNode *node, const xmlChar *name) { | 
6882  | 0  |     xmlAttrPtr prop;  | 
6883  |  | 
  | 
6884  | 0  |     prop = xmlGetPropNodeInternal(node, name, NULL, xmlCheckDTD);  | 
6885  | 0  |     if (prop == NULL)  | 
6886  | 0  |   return(NULL);  | 
6887  | 0  |     return(xmlGetPropNodeValueInternal(prop));  | 
6888  | 0  | }  | 
6889  |  |  | 
6890  |  | /**  | 
6891  |  |  * xmlGetNsProp:  | 
6892  |  |  * @node:  the node  | 
6893  |  |  * @name:  the attribute name  | 
6894  |  |  * @nameSpace:  the URI of the namespace  | 
6895  |  |  *  | 
6896  |  |  * Search and get the value of an attribute associated to a node  | 
6897  |  |  * This attribute has to be anchored in the namespace specified.  | 
6898  |  |  * This does the entity substitution.  | 
6899  |  |  * This function looks in DTD attribute declaration for #FIXED or  | 
6900  |  |  * default declaration values unless DTD use has been turned off.  | 
6901  |  |  *  | 
6902  |  |  * Returns the attribute value or NULL if not found.  | 
6903  |  |  *     It's up to the caller to free the memory with xmlFree().  | 
6904  |  |  */  | 
6905  |  | xmlChar *  | 
6906  | 3.73M  | xmlGetNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace) { | 
6907  | 3.73M  |     xmlAttrPtr prop;  | 
6908  |  |  | 
6909  | 3.73M  |     prop = xmlGetPropNodeInternal(node, name, nameSpace, xmlCheckDTD);  | 
6910  | 3.73M  |     if (prop == NULL)  | 
6911  | 3.73M  |   return(NULL);  | 
6912  | 0  |     return(xmlGetPropNodeValueInternal(prop));  | 
6913  | 3.73M  | }  | 
6914  |  |  | 
6915  |  | #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)  | 
6916  |  | /**  | 
6917  |  |  * xmlUnsetProp:  | 
6918  |  |  * @node:  the node  | 
6919  |  |  * @name:  the attribute name  | 
6920  |  |  *  | 
6921  |  |  * Remove an attribute carried by a node.  | 
6922  |  |  * This handles only attributes in no namespace.  | 
6923  |  |  * Returns 0 if successful, -1 if not found  | 
6924  |  |  */  | 
6925  |  | int  | 
6926  | 0  | xmlUnsetProp(xmlNodePtr node, const xmlChar *name) { | 
6927  | 0  |     xmlAttrPtr prop;  | 
6928  |  | 
  | 
6929  | 0  |     prop = xmlGetPropNodeInternal(node, name, NULL, 0);  | 
6930  | 0  |     if (prop == NULL)  | 
6931  | 0  |   return(-1);  | 
6932  | 0  |     xmlUnlinkNode((xmlNodePtr) prop);  | 
6933  | 0  |     xmlFreeProp(prop);  | 
6934  | 0  |     return(0);  | 
6935  | 0  | }  | 
6936  |  |  | 
6937  |  | /**  | 
6938  |  |  * xmlUnsetNsProp:  | 
6939  |  |  * @node:  the node  | 
6940  |  |  * @ns:  the namespace definition  | 
6941  |  |  * @name:  the attribute name  | 
6942  |  |  *  | 
6943  |  |  * Remove an attribute carried by a node.  | 
6944  |  |  * Returns 0 if successful, -1 if not found  | 
6945  |  |  */  | 
6946  |  | int  | 
6947  | 0  | xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) { | 
6948  | 0  |     xmlAttrPtr prop;  | 
6949  |  | 
  | 
6950  | 0  |     prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);  | 
6951  | 0  |     if (prop == NULL)  | 
6952  | 0  |   return(-1);  | 
6953  | 0  |     xmlUnlinkNode((xmlNodePtr) prop);  | 
6954  | 0  |     xmlFreeProp(prop);  | 
6955  | 0  |     return(0);  | 
6956  | 0  | }  | 
6957  |  | #endif  | 
6958  |  |  | 
6959  |  | #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED)  | 
6960  |  | /**  | 
6961  |  |  * xmlSetProp:  | 
6962  |  |  * @node:  the node  | 
6963  |  |  * @name:  the attribute name (a QName)  | 
6964  |  |  * @value:  the attribute value  | 
6965  |  |  *  | 
6966  |  |  * Set (or reset) an attribute carried by a node.  | 
6967  |  |  * If @name has a prefix, then the corresponding  | 
6968  |  |  * namespace-binding will be used, if in scope; it is an  | 
6969  |  |  * error it there's no such ns-binding for the prefix in  | 
6970  |  |  * scope.  | 
6971  |  |  * Returns the attribute pointer.  | 
6972  |  |  *  | 
6973  |  |  */  | 
6974  |  | xmlAttrPtr  | 
6975  | 0  | xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { | 
6976  | 0  |     int len;  | 
6977  | 0  |     const xmlChar *nqname;  | 
6978  |  | 
  | 
6979  | 0  |     if ((node == NULL) || (name == NULL) || (node->type != XML_ELEMENT_NODE))  | 
6980  | 0  |   return(NULL);  | 
6981  |  |  | 
6982  |  |     /*  | 
6983  |  |      * handle QNames  | 
6984  |  |      */  | 
6985  | 0  |     nqname = xmlSplitQName3(name, &len);  | 
6986  | 0  |     if (nqname != NULL) { | 
6987  | 0  |         xmlNsPtr ns;  | 
6988  | 0  |   xmlChar *prefix = xmlStrndup(name, len);  | 
6989  | 0  |   ns = xmlSearchNs(node->doc, node, prefix);  | 
6990  | 0  |   if (prefix != NULL)  | 
6991  | 0  |       xmlFree(prefix);  | 
6992  | 0  |   if (ns != NULL)  | 
6993  | 0  |       return(xmlSetNsProp(node, ns, nqname, value));  | 
6994  | 0  |     }  | 
6995  | 0  |     return(xmlSetNsProp(node, NULL, name, value));  | 
6996  | 0  | }  | 
6997  |  |  | 
6998  |  | /**  | 
6999  |  |  * xmlSetNsProp:  | 
7000  |  |  * @node:  the node  | 
7001  |  |  * @ns:  the namespace definition  | 
7002  |  |  * @name:  the attribute name  | 
7003  |  |  * @value:  the attribute value  | 
7004  |  |  *  | 
7005  |  |  * Set (or reset) an attribute carried by a node.  | 
7006  |  |  * The ns structure must be in scope, this is not checked  | 
7007  |  |  *  | 
7008  |  |  * Returns the attribute pointer.  | 
7009  |  |  */  | 
7010  |  | xmlAttrPtr  | 
7011  |  | xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,  | 
7012  |  |        const xmlChar *value)  | 
7013  | 0  | { | 
7014  | 0  |     xmlAttrPtr prop;  | 
7015  |  | 
  | 
7016  | 0  |     if (ns && (ns->href == NULL))  | 
7017  | 0  |   return(NULL);  | 
7018  | 0  |     prop = xmlGetPropNodeInternal(node, name, (ns != NULL) ? ns->href : NULL, 0);  | 
7019  | 0  |     if (prop != NULL) { | 
7020  |  |   /*  | 
7021  |  |   * Modify the attribute's value.  | 
7022  |  |   */  | 
7023  | 0  |   if (prop->atype == XML_ATTRIBUTE_ID) { | 
7024  | 0  |       xmlRemoveID(node->doc, prop);  | 
7025  | 0  |       prop->atype = XML_ATTRIBUTE_ID;  | 
7026  | 0  |   }  | 
7027  | 0  |   if (prop->children != NULL)  | 
7028  | 0  |       xmlFreeNodeList(prop->children);  | 
7029  | 0  |   prop->children = NULL;  | 
7030  | 0  |   prop->last = NULL;  | 
7031  | 0  |   prop->ns = ns;  | 
7032  | 0  |   if (value != NULL) { | 
7033  | 0  |       xmlNodePtr tmp;  | 
7034  |  | 
  | 
7035  | 0  |       prop->children = xmlNewDocText(node->doc, value);  | 
7036  | 0  |       prop->last = NULL;  | 
7037  | 0  |       tmp = prop->children;  | 
7038  | 0  |       while (tmp != NULL) { | 
7039  | 0  |     tmp->parent = (xmlNodePtr) prop;  | 
7040  | 0  |     if (tmp->next == NULL)  | 
7041  | 0  |         prop->last = tmp;  | 
7042  | 0  |     tmp = tmp->next;  | 
7043  | 0  |       }  | 
7044  | 0  |   }  | 
7045  | 0  |   if (prop->atype == XML_ATTRIBUTE_ID)  | 
7046  | 0  |       xmlAddID(NULL, node->doc, value, prop);  | 
7047  | 0  |   return(prop);  | 
7048  | 0  |     }  | 
7049  |  |     /*  | 
7050  |  |     * No equal attr found; create a new one.  | 
7051  |  |     */  | 
7052  | 0  |     return(xmlNewPropInternal(node, ns, name, value, 0));  | 
7053  | 0  | }  | 
7054  |  |  | 
7055  |  | #endif /* LIBXML_TREE_ENABLED */  | 
7056  |  |  | 
7057  |  | /**  | 
7058  |  |  * xmlNodeIsText:  | 
7059  |  |  * @node:  the node  | 
7060  |  |  *  | 
7061  |  |  * Is this node a Text node ?  | 
7062  |  |  * Returns 1 yes, 0 no  | 
7063  |  |  */  | 
7064  |  | int  | 
7065  | 0  | xmlNodeIsText(const xmlNode *node) { | 
7066  | 0  |     if (node == NULL) return(0);  | 
7067  |  |  | 
7068  | 0  |     if (node->type == XML_TEXT_NODE) return(1);  | 
7069  | 0  |     return(0);  | 
7070  | 0  | }  | 
7071  |  |  | 
7072  |  | /**  | 
7073  |  |  * xmlIsBlankNode:  | 
7074  |  |  * @node:  the node  | 
7075  |  |  *  | 
7076  |  |  * Checks whether this node is an empty or whitespace only  | 
7077  |  |  * (and possibly ignorable) text-node.  | 
7078  |  |  *  | 
7079  |  |  * Returns 1 yes, 0 no  | 
7080  |  |  */  | 
7081  |  | int  | 
7082  | 0  | xmlIsBlankNode(const xmlNode *node) { | 
7083  | 0  |     const xmlChar *cur;  | 
7084  | 0  |     if (node == NULL) return(0);  | 
7085  |  |  | 
7086  | 0  |     if ((node->type != XML_TEXT_NODE) &&  | 
7087  | 0  |         (node->type != XML_CDATA_SECTION_NODE))  | 
7088  | 0  |   return(0);  | 
7089  | 0  |     if (node->content == NULL) return(1);  | 
7090  | 0  |     cur = node->content;  | 
7091  | 0  |     while (*cur != 0) { | 
7092  | 0  |   if (!IS_BLANK_CH(*cur)) return(0);  | 
7093  | 0  |   cur++;  | 
7094  | 0  |     }  | 
7095  |  |  | 
7096  | 0  |     return(1);  | 
7097  | 0  | }  | 
7098  |  |  | 
7099  |  | /**  | 
7100  |  |  * xmlTextConcat:  | 
7101  |  |  * @node:  the node  | 
7102  |  |  * @content:  the content  | 
7103  |  |  * @len:  @content length  | 
7104  |  |  *  | 
7105  |  |  * Concat the given string at the end of the existing node content  | 
7106  |  |  *  | 
7107  |  |  * Returns -1 in case of error, 0 otherwise  | 
7108  |  |  */  | 
7109  |  |  | 
7110  |  | int  | 
7111  | 0  | xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) { | 
7112  | 0  |     if (node == NULL) return(-1);  | 
7113  |  |  | 
7114  | 0  |     if ((node->type != XML_TEXT_NODE) &&  | 
7115  | 0  |         (node->type != XML_CDATA_SECTION_NODE) &&  | 
7116  | 0  |   (node->type != XML_COMMENT_NODE) &&  | 
7117  | 0  |   (node->type != XML_PI_NODE)) { | 
7118  |  | #ifdef DEBUG_TREE  | 
7119  |  |   xmlGenericError(xmlGenericErrorContext,  | 
7120  |  |     "xmlTextConcat: node is not text nor CDATA\n");  | 
7121  |  | #endif  | 
7122  | 0  |         return(-1);  | 
7123  | 0  |     }  | 
7124  |  |     /* need to check if content is currently in the dictionary */  | 
7125  | 0  |     if ((node->content == (xmlChar *) &(node->properties)) ||  | 
7126  | 0  |         ((node->doc != NULL) && (node->doc->dict != NULL) &&  | 
7127  | 0  |     xmlDictOwns(node->doc->dict, node->content))) { | 
7128  | 0  |   node->content = xmlStrncatNew(node->content, content, len);  | 
7129  | 0  |     } else { | 
7130  | 0  |         node->content = xmlStrncat(node->content, content, len);  | 
7131  | 0  |     }  | 
7132  | 0  |     node->properties = NULL;  | 
7133  | 0  |     if (node->content == NULL)  | 
7134  | 0  |         return(-1);  | 
7135  | 0  |     return(0);  | 
7136  | 0  | }  | 
7137  |  |  | 
7138  |  | /************************************************************************  | 
7139  |  |  *                  *  | 
7140  |  |  *      Output : to a FILE or in memory     *  | 
7141  |  |  *                  *  | 
7142  |  |  ************************************************************************/  | 
7143  |  |  | 
7144  |  | /**  | 
7145  |  |  * xmlBufferCreate:  | 
7146  |  |  *  | 
7147  |  |  * routine to create an XML buffer.  | 
7148  |  |  * returns the new structure.  | 
7149  |  |  */  | 
7150  |  | xmlBufferPtr  | 
7151  | 359k  | xmlBufferCreate(void) { | 
7152  | 359k  |     xmlBufferPtr ret;  | 
7153  |  |  | 
7154  | 359k  |     ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));  | 
7155  | 359k  |     if (ret == NULL) { | 
7156  | 0  |   xmlTreeErrMemory("creating buffer"); | 
7157  | 0  |         return(NULL);  | 
7158  | 0  |     }  | 
7159  | 359k  |     ret->use = 0;  | 
7160  | 359k  |     ret->size = xmlDefaultBufferSize;  | 
7161  | 359k  |     ret->alloc = xmlBufferAllocScheme;  | 
7162  | 359k  |     ret->content = (xmlChar *) xmlMallocAtomic(ret->size);  | 
7163  | 359k  |     if (ret->content == NULL) { | 
7164  | 0  |   xmlTreeErrMemory("creating buffer"); | 
7165  | 0  |   xmlFree(ret);  | 
7166  | 0  |         return(NULL);  | 
7167  | 0  |     }  | 
7168  | 359k  |     ret->content[0] = 0;  | 
7169  | 359k  |     ret->contentIO = NULL;  | 
7170  | 359k  |     return(ret);  | 
7171  | 359k  | }  | 
7172  |  |  | 
7173  |  | /**  | 
7174  |  |  * xmlBufferCreateSize:  | 
7175  |  |  * @size: initial size of buffer  | 
7176  |  |  *  | 
7177  |  |  * routine to create an XML buffer.  | 
7178  |  |  * returns the new structure.  | 
7179  |  |  */  | 
7180  |  | xmlBufferPtr  | 
7181  | 3.65k  | xmlBufferCreateSize(size_t size) { | 
7182  | 3.65k  |     xmlBufferPtr ret;  | 
7183  |  |  | 
7184  | 3.65k  |     if (size >= UINT_MAX)  | 
7185  | 0  |         return(NULL);  | 
7186  | 3.65k  |     ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));  | 
7187  | 3.65k  |     if (ret == NULL) { | 
7188  | 0  |   xmlTreeErrMemory("creating buffer"); | 
7189  | 0  |         return(NULL);  | 
7190  | 0  |     }  | 
7191  | 3.65k  |     ret->use = 0;  | 
7192  | 3.65k  |     ret->alloc = xmlBufferAllocScheme;  | 
7193  | 3.65k  |     ret->size = (size ? size + 1 : 0);         /* +1 for ending null */  | 
7194  | 3.65k  |     if (ret->size){ | 
7195  | 3.65k  |         ret->content = (xmlChar *) xmlMallocAtomic(ret->size);  | 
7196  | 3.65k  |         if (ret->content == NULL) { | 
7197  | 0  |       xmlTreeErrMemory("creating buffer"); | 
7198  | 0  |             xmlFree(ret);  | 
7199  | 0  |             return(NULL);  | 
7200  | 0  |         }  | 
7201  | 3.65k  |         ret->content[0] = 0;  | 
7202  | 3.65k  |     } else  | 
7203  | 0  |   ret->content = NULL;  | 
7204  | 3.65k  |     ret->contentIO = NULL;  | 
7205  | 3.65k  |     return(ret);  | 
7206  | 3.65k  | }  | 
7207  |  |  | 
7208  |  | /**  | 
7209  |  |  * xmlBufferDetach:  | 
7210  |  |  * @buf:  the buffer  | 
7211  |  |  *  | 
7212  |  |  * Remove the string contained in a buffer and gie it back to the  | 
7213  |  |  * caller. The buffer is reset to an empty content.  | 
7214  |  |  * This doesn't work with immutable buffers as they can't be reset.  | 
7215  |  |  *  | 
7216  |  |  * Returns the previous string contained by the buffer.  | 
7217  |  |  */  | 
7218  |  | xmlChar *  | 
7219  | 3.83k  | xmlBufferDetach(xmlBufferPtr buf) { | 
7220  | 3.83k  |     xmlChar *ret;  | 
7221  |  |  | 
7222  | 3.83k  |     if (buf == NULL)  | 
7223  | 0  |         return(NULL);  | 
7224  |  |  | 
7225  | 3.83k  |     ret = buf->content;  | 
7226  | 3.83k  |     buf->content = NULL;  | 
7227  | 3.83k  |     buf->size = 0;  | 
7228  | 3.83k  |     buf->use = 0;  | 
7229  |  |  | 
7230  | 3.83k  |     return ret;  | 
7231  | 3.83k  | }  | 
7232  |  |  | 
7233  |  |  | 
7234  |  | /**  | 
7235  |  |  * xmlBufferCreateStatic:  | 
7236  |  |  * @mem: the memory area  | 
7237  |  |  * @size:  the size in byte  | 
7238  |  |  *  | 
7239  |  |  * Create an XML buffer initialized with bytes.  | 
7240  |  |  */  | 
7241  |  | xmlBufferPtr  | 
7242  | 0  | xmlBufferCreateStatic(void *mem, size_t size) { | 
7243  | 0  |     xmlBufferPtr buf = xmlBufferCreateSize(size);  | 
7244  |  | 
  | 
7245  | 0  |     xmlBufferAdd(buf, mem, size);  | 
7246  | 0  |     return(buf);  | 
7247  | 0  | }  | 
7248  |  |  | 
7249  |  | /**  | 
7250  |  |  * xmlBufferSetAllocationScheme:  | 
7251  |  |  * @buf:  the buffer to tune  | 
7252  |  |  * @scheme:  allocation scheme to use  | 
7253  |  |  *  | 
7254  |  |  * Sets the allocation scheme for this buffer  | 
7255  |  |  */  | 
7256  |  | void  | 
7257  |  | xmlBufferSetAllocationScheme(xmlBufferPtr buf,  | 
7258  | 11.6k  |                              xmlBufferAllocationScheme scheme) { | 
7259  | 11.6k  |     if (buf == NULL) { | 
7260  |  | #ifdef DEBUG_BUFFER  | 
7261  |  |         xmlGenericError(xmlGenericErrorContext,  | 
7262  |  |     "xmlBufferSetAllocationScheme: buf == NULL\n");  | 
7263  |  | #endif  | 
7264  | 0  |         return;  | 
7265  | 0  |     }  | 
7266  | 11.6k  |     if (buf->alloc == XML_BUFFER_ALLOC_IO) return;  | 
7267  | 11.6k  |     if ((scheme == XML_BUFFER_ALLOC_DOUBLEIT) ||  | 
7268  | 11.6k  |         (scheme == XML_BUFFER_ALLOC_EXACT) ||  | 
7269  | 11.6k  |         (scheme == XML_BUFFER_ALLOC_HYBRID))  | 
7270  | 11.6k  |   buf->alloc = scheme;  | 
7271  | 11.6k  | }  | 
7272  |  |  | 
7273  |  | /**  | 
7274  |  |  * xmlBufferFree:  | 
7275  |  |  * @buf:  the buffer to free  | 
7276  |  |  *  | 
7277  |  |  * Frees an XML buffer. It frees both the content and the structure which  | 
7278  |  |  * encapsulate it.  | 
7279  |  |  */  | 
7280  |  | void  | 
7281  | 362k  | xmlBufferFree(xmlBufferPtr buf) { | 
7282  | 362k  |     if (buf == NULL) { | 
7283  |  | #ifdef DEBUG_BUFFER  | 
7284  |  |         xmlGenericError(xmlGenericErrorContext,  | 
7285  |  |     "xmlBufferFree: buf == NULL\n");  | 
7286  |  | #endif  | 
7287  | 0  |   return;  | 
7288  | 0  |     }  | 
7289  |  |  | 
7290  | 362k  |     if ((buf->alloc == XML_BUFFER_ALLOC_IO) &&  | 
7291  | 362k  |         (buf->contentIO != NULL)) { | 
7292  | 0  |         xmlFree(buf->contentIO);  | 
7293  | 362k  |     } else if (buf->content != NULL) { | 
7294  | 359k  |         xmlFree(buf->content);  | 
7295  | 359k  |     }  | 
7296  | 362k  |     xmlFree(buf);  | 
7297  | 362k  | }  | 
7298  |  |  | 
7299  |  | /**  | 
7300  |  |  * xmlBufferEmpty:  | 
7301  |  |  * @buf:  the buffer  | 
7302  |  |  *  | 
7303  |  |  * empty a buffer.  | 
7304  |  |  */  | 
7305  |  | void  | 
7306  | 0  | xmlBufferEmpty(xmlBufferPtr buf) { | 
7307  | 0  |     if (buf == NULL) return;  | 
7308  | 0  |     if (buf->content == NULL) return;  | 
7309  | 0  |     buf->use = 0;  | 
7310  | 0  |     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) { | 
7311  | 0  |         size_t start_buf = buf->content - buf->contentIO;  | 
7312  |  | 
  | 
7313  | 0  |   buf->size += start_buf;  | 
7314  | 0  |         buf->content = buf->contentIO;  | 
7315  | 0  |         buf->content[0] = 0;  | 
7316  | 0  |     } else { | 
7317  | 0  |         buf->content[0] = 0;  | 
7318  | 0  |     }  | 
7319  | 0  | }  | 
7320  |  |  | 
7321  |  | /**  | 
7322  |  |  * xmlBufferShrink:  | 
7323  |  |  * @buf:  the buffer to dump  | 
7324  |  |  * @len:  the number of xmlChar to remove  | 
7325  |  |  *  | 
7326  |  |  * Remove the beginning of an XML buffer.  | 
7327  |  |  *  | 
7328  |  |  * Returns the number of #xmlChar removed, or -1 in case of failure.  | 
7329  |  |  */  | 
7330  |  | int  | 
7331  | 0  | xmlBufferShrink(xmlBufferPtr buf, unsigned int len) { | 
7332  | 0  |     if (buf == NULL) return(-1);  | 
7333  | 0  |     if (len == 0) return(0);  | 
7334  | 0  |     if (len > buf->use) return(-1);  | 
7335  |  |  | 
7336  | 0  |     buf->use -= len;  | 
7337  | 0  |     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) { | 
7338  |  |   /*  | 
7339  |  |    * we just move the content pointer, but also make sure  | 
7340  |  |    * the perceived buffer size has shrunk accordingly  | 
7341  |  |    */  | 
7342  | 0  |         buf->content += len;  | 
7343  | 0  |   buf->size -= len;  | 
7344  |  |  | 
7345  |  |         /*  | 
7346  |  |    * sometimes though it maybe be better to really shrink  | 
7347  |  |    * on IO buffers  | 
7348  |  |    */  | 
7349  | 0  |   if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) { | 
7350  | 0  |       size_t start_buf = buf->content - buf->contentIO;  | 
7351  | 0  |       if (start_buf >= buf->size) { | 
7352  | 0  |     memmove(buf->contentIO, &buf->content[0], buf->use);  | 
7353  | 0  |     buf->content = buf->contentIO;  | 
7354  | 0  |     buf->content[buf->use] = 0;  | 
7355  | 0  |     buf->size += start_buf;  | 
7356  | 0  |       }  | 
7357  | 0  |   }  | 
7358  | 0  |     } else { | 
7359  | 0  |   memmove(buf->content, &buf->content[len], buf->use);  | 
7360  | 0  |   buf->content[buf->use] = 0;  | 
7361  | 0  |     }  | 
7362  | 0  |     return(len);  | 
7363  | 0  | }  | 
7364  |  |  | 
7365  |  | /**  | 
7366  |  |  * xmlBufferGrow:  | 
7367  |  |  * @buf:  the buffer  | 
7368  |  |  * @len:  the minimum free size to allocate  | 
7369  |  |  *  | 
7370  |  |  * Grow the available space of an XML buffer.  | 
7371  |  |  *  | 
7372  |  |  * Returns the new available space or -1 in case of error  | 
7373  |  |  */  | 
7374  |  | int  | 
7375  | 0  | xmlBufferGrow(xmlBufferPtr buf, unsigned int len) { | 
7376  | 0  |     unsigned int size;  | 
7377  | 0  |     xmlChar *newbuf;  | 
7378  |  | 
  | 
7379  | 0  |     if (buf == NULL) return(-1);  | 
7380  |  |  | 
7381  | 0  |     if (len < buf->size - buf->use)  | 
7382  | 0  |         return(0);  | 
7383  | 0  |     if (len >= UINT_MAX - buf->use) { | 
7384  | 0  |         xmlTreeErrMemory("growing buffer past UINT_MAX"); | 
7385  | 0  |         return(-1);  | 
7386  | 0  |     }  | 
7387  |  |  | 
7388  | 0  |     if (buf->size > (size_t) len) { | 
7389  | 0  |         size = buf->size > UINT_MAX / 2 ? UINT_MAX : buf->size * 2;  | 
7390  | 0  |     } else { | 
7391  | 0  |         size = buf->use + len;  | 
7392  | 0  |         size = size > UINT_MAX - 100 ? UINT_MAX : size + 100;  | 
7393  | 0  |     }  | 
7394  |  | 
  | 
7395  | 0  |     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) { | 
7396  | 0  |         size_t start_buf = buf->content - buf->contentIO;  | 
7397  |  | 
  | 
7398  | 0  |   newbuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + size);  | 
7399  | 0  |   if (newbuf == NULL) { | 
7400  | 0  |       xmlTreeErrMemory("growing buffer"); | 
7401  | 0  |       return(-1);  | 
7402  | 0  |   }  | 
7403  | 0  |   buf->contentIO = newbuf;  | 
7404  | 0  |   buf->content = newbuf + start_buf;  | 
7405  | 0  |     } else { | 
7406  | 0  |   newbuf = (xmlChar *) xmlRealloc(buf->content, size);  | 
7407  | 0  |   if (newbuf == NULL) { | 
7408  | 0  |       xmlTreeErrMemory("growing buffer"); | 
7409  | 0  |       return(-1);  | 
7410  | 0  |   }  | 
7411  | 0  |   buf->content = newbuf;  | 
7412  | 0  |     }  | 
7413  | 0  |     buf->size = size;  | 
7414  | 0  |     return(buf->size - buf->use - 1);  | 
7415  | 0  | }  | 
7416  |  |  | 
7417  |  | /**  | 
7418  |  |  * xmlBufferDump:  | 
7419  |  |  * @file:  the file output  | 
7420  |  |  * @buf:  the buffer to dump  | 
7421  |  |  *  | 
7422  |  |  * Dumps an XML buffer to  a FILE *.  | 
7423  |  |  * Returns the number of #xmlChar written  | 
7424  |  |  */  | 
7425  |  | int  | 
7426  | 0  | xmlBufferDump(FILE *file, xmlBufferPtr buf) { | 
7427  | 0  |     size_t ret;  | 
7428  |  | 
  | 
7429  | 0  |     if (buf == NULL) { | 
7430  |  | #ifdef DEBUG_BUFFER  | 
7431  |  |         xmlGenericError(xmlGenericErrorContext,  | 
7432  |  |     "xmlBufferDump: buf == NULL\n");  | 
7433  |  | #endif  | 
7434  | 0  |   return(0);  | 
7435  | 0  |     }  | 
7436  | 0  |     if (buf->content == NULL) { | 
7437  |  | #ifdef DEBUG_BUFFER  | 
7438  |  |         xmlGenericError(xmlGenericErrorContext,  | 
7439  |  |     "xmlBufferDump: buf->content == NULL\n");  | 
7440  |  | #endif  | 
7441  | 0  |   return(0);  | 
7442  | 0  |     }  | 
7443  | 0  |     if (file == NULL)  | 
7444  | 0  |   file = stdout;  | 
7445  | 0  |     ret = fwrite(buf->content, 1, buf->use, file);  | 
7446  | 0  |     return(ret > INT_MAX ? INT_MAX : ret);  | 
7447  | 0  | }  | 
7448  |  |  | 
7449  |  | /**  | 
7450  |  |  * xmlBufferContent:  | 
7451  |  |  * @buf:  the buffer  | 
7452  |  |  *  | 
7453  |  |  * Function to extract the content of a buffer  | 
7454  |  |  *  | 
7455  |  |  * Returns the internal content  | 
7456  |  |  */  | 
7457  |  |  | 
7458  |  | const xmlChar *  | 
7459  |  | xmlBufferContent(const xmlBuffer *buf)  | 
7460  | 359k  | { | 
7461  | 359k  |     if(!buf)  | 
7462  | 0  |         return NULL;  | 
7463  |  |  | 
7464  | 359k  |     return buf->content;  | 
7465  | 359k  | }  | 
7466  |  |  | 
7467  |  | /**  | 
7468  |  |  * xmlBufferLength:  | 
7469  |  |  * @buf:  the buffer  | 
7470  |  |  *  | 
7471  |  |  * Function to get the length of a buffer  | 
7472  |  |  *  | 
7473  |  |  * Returns the length of data in the internal content  | 
7474  |  |  */  | 
7475  |  |  | 
7476  |  | int  | 
7477  |  | xmlBufferLength(const xmlBuffer *buf)  | 
7478  | 7.83k  | { | 
7479  | 7.83k  |     if(!buf)  | 
7480  | 0  |         return 0;  | 
7481  |  |  | 
7482  | 7.83k  |     return buf->use;  | 
7483  | 7.83k  | }  | 
7484  |  |  | 
7485  |  | /**  | 
7486  |  |  * xmlBufferResize:  | 
7487  |  |  * @buf:  the buffer to resize  | 
7488  |  |  * @size:  the desired size  | 
7489  |  |  *  | 
7490  |  |  * Resize a buffer to accommodate minimum size of @size.  | 
7491  |  |  *  | 
7492  |  |  * Returns  0 in case of problems, 1 otherwise  | 
7493  |  |  */  | 
7494  |  | int  | 
7495  |  | xmlBufferResize(xmlBufferPtr buf, unsigned int size)  | 
7496  | 206k  | { | 
7497  | 206k  |     unsigned int newSize;  | 
7498  | 206k  |     xmlChar* rebuf = NULL;  | 
7499  | 206k  |     size_t start_buf;  | 
7500  |  |  | 
7501  | 206k  |     if (buf == NULL)  | 
7502  | 0  |         return(0);  | 
7503  |  |  | 
7504  |  |     /* Don't resize if we don't have to */  | 
7505  | 206k  |     if (size < buf->size)  | 
7506  | 0  |         return 1;  | 
7507  |  |  | 
7508  | 206k  |     if (size > UINT_MAX - 10) { | 
7509  | 0  |         xmlTreeErrMemory("growing buffer past UINT_MAX"); | 
7510  | 0  |         return 0;  | 
7511  | 0  |     }  | 
7512  |  |  | 
7513  |  |     /* figure out new size */  | 
7514  | 206k  |     switch (buf->alloc){ | 
7515  | 0  |   case XML_BUFFER_ALLOC_IO:  | 
7516  | 969  |   case XML_BUFFER_ALLOC_DOUBLEIT:  | 
7517  |  |       /*take care of empty case*/  | 
7518  | 969  |             if (buf->size == 0)  | 
7519  | 0  |                 newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);  | 
7520  | 969  |             else  | 
7521  | 969  |                 newSize = buf->size;  | 
7522  | 2.26k  |       while (size > newSize) { | 
7523  | 1.29k  |           if (newSize > UINT_MAX / 2) { | 
7524  | 0  |               xmlTreeErrMemory("growing buffer"); | 
7525  | 0  |               return 0;  | 
7526  | 0  |           }  | 
7527  | 1.29k  |           newSize *= 2;  | 
7528  | 1.29k  |       }  | 
7529  | 969  |       break;  | 
7530  | 205k  |   case XML_BUFFER_ALLOC_EXACT:  | 
7531  | 205k  |       newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);  | 
7532  | 205k  |       break;  | 
7533  | 0  |         case XML_BUFFER_ALLOC_HYBRID:  | 
7534  | 0  |             if (buf->use < BASE_BUFFER_SIZE)  | 
7535  | 0  |                 newSize = size;  | 
7536  | 0  |             else { | 
7537  | 0  |                 newSize = buf->size;  | 
7538  | 0  |                 while (size > newSize) { | 
7539  | 0  |                     if (newSize > UINT_MAX / 2) { | 
7540  | 0  |                         xmlTreeErrMemory("growing buffer"); | 
7541  | 0  |                         return 0;  | 
7542  | 0  |                     }  | 
7543  | 0  |                     newSize *= 2;  | 
7544  | 0  |                 }  | 
7545  | 0  |             }  | 
7546  | 0  |             break;  | 
7547  |  |  | 
7548  | 0  |   default:  | 
7549  | 0  |       newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);  | 
7550  | 0  |       break;  | 
7551  | 206k  |     }  | 
7552  |  |  | 
7553  | 206k  |     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) { | 
7554  | 0  |         start_buf = buf->content - buf->contentIO;  | 
7555  |  | 
  | 
7556  | 0  |         if (start_buf > newSize) { | 
7557  |  |       /* move data back to start */  | 
7558  | 0  |       memmove(buf->contentIO, buf->content, buf->use);  | 
7559  | 0  |       buf->content = buf->contentIO;  | 
7560  | 0  |       buf->content[buf->use] = 0;  | 
7561  | 0  |       buf->size += start_buf;  | 
7562  | 0  |   } else { | 
7563  | 0  |       rebuf = (xmlChar *) xmlRealloc(buf->contentIO, start_buf + newSize);  | 
7564  | 0  |       if (rebuf == NULL) { | 
7565  | 0  |     xmlTreeErrMemory("growing buffer"); | 
7566  | 0  |     return 0;  | 
7567  | 0  |       }  | 
7568  | 0  |       buf->contentIO = rebuf;  | 
7569  | 0  |       buf->content = rebuf + start_buf;  | 
7570  | 0  |   }  | 
7571  | 206k  |     } else { | 
7572  | 206k  |   if (buf->content == NULL) { | 
7573  | 0  |       rebuf = (xmlChar *) xmlMallocAtomic(newSize);  | 
7574  | 0  |       buf->use = 0;  | 
7575  | 0  |       rebuf[buf->use] = 0;  | 
7576  | 206k  |   } else if (buf->size - buf->use < 100) { | 
7577  | 205k  |       rebuf = (xmlChar *) xmlRealloc(buf->content, newSize);  | 
7578  | 205k  |         } else { | 
7579  |  |       /*  | 
7580  |  |        * if we are reallocating a buffer far from being full, it's  | 
7581  |  |        * better to make a new allocation and copy only the used range  | 
7582  |  |        * and free the old one.  | 
7583  |  |        */  | 
7584  | 527  |       rebuf = (xmlChar *) xmlMallocAtomic(newSize);  | 
7585  | 527  |       if (rebuf != NULL) { | 
7586  | 527  |     memcpy(rebuf, buf->content, buf->use);  | 
7587  | 527  |     xmlFree(buf->content);  | 
7588  | 527  |     rebuf[buf->use] = 0;  | 
7589  | 527  |       }  | 
7590  | 527  |   }  | 
7591  | 206k  |   if (rebuf == NULL) { | 
7592  | 0  |       xmlTreeErrMemory("growing buffer"); | 
7593  | 0  |       return 0;  | 
7594  | 0  |   }  | 
7595  | 206k  |   buf->content = rebuf;  | 
7596  | 206k  |     }  | 
7597  | 206k  |     buf->size = newSize;  | 
7598  |  |  | 
7599  | 206k  |     return 1;  | 
7600  | 206k  | }  | 
7601  |  |  | 
7602  |  | /**  | 
7603  |  |  * xmlBufferAdd:  | 
7604  |  |  * @buf:  the buffer to dump  | 
7605  |  |  * @str:  the #xmlChar string  | 
7606  |  |  * @len:  the number of #xmlChar to add  | 
7607  |  |  *  | 
7608  |  |  * Add a string range to an XML buffer. if len == -1, the length of  | 
7609  |  |  * str is recomputed.  | 
7610  |  |  *  | 
7611  |  |  * Returns 0 successful, a positive error code number otherwise  | 
7612  |  |  *         and -1 in case of internal or API error.  | 
7613  |  |  */  | 
7614  |  | int  | 
7615  | 7.49M  | xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) { | 
7616  | 7.49M  |     unsigned int needSize;  | 
7617  |  |  | 
7618  | 7.49M  |     if ((str == NULL) || (buf == NULL)) { | 
7619  | 0  |   return -1;  | 
7620  | 0  |     }  | 
7621  | 7.49M  |     if (len < -1) { | 
7622  |  | #ifdef DEBUG_BUFFER  | 
7623  |  |         xmlGenericError(xmlGenericErrorContext,  | 
7624  |  |     "xmlBufferAdd: len < 0\n");  | 
7625  |  | #endif  | 
7626  | 0  |   return -1;  | 
7627  | 0  |     }  | 
7628  | 7.49M  |     if (len == 0) return 0;  | 
7629  |  |  | 
7630  | 7.49M  |     if (len < 0)  | 
7631  | 553k  |         len = xmlStrlen(str);  | 
7632  |  |  | 
7633  | 7.49M  |     if (len < 0) return -1;  | 
7634  | 7.49M  |     if (len == 0) return 0;  | 
7635  |  |  | 
7636  |  |     /* Note that both buf->size and buf->use can be zero here. */  | 
7637  | 7.46M  |     if ((unsigned) len >= buf->size - buf->use) { | 
7638  | 206k  |         if ((unsigned) len >= UINT_MAX - buf->use) { | 
7639  | 0  |             xmlTreeErrMemory("growing buffer past UINT_MAX"); | 
7640  | 0  |             return XML_ERR_NO_MEMORY;  | 
7641  | 0  |         }  | 
7642  | 206k  |         needSize = buf->use + len + 1;  | 
7643  | 206k  |         if (!xmlBufferResize(buf, needSize)){ | 
7644  | 0  |       xmlTreeErrMemory("growing buffer"); | 
7645  | 0  |             return XML_ERR_NO_MEMORY;  | 
7646  | 0  |         }  | 
7647  | 206k  |     }  | 
7648  |  |  | 
7649  | 7.46M  |     memmove(&buf->content[buf->use], str, len);  | 
7650  | 7.46M  |     buf->use += len;  | 
7651  | 7.46M  |     buf->content[buf->use] = 0;  | 
7652  | 7.46M  |     return 0;  | 
7653  | 7.46M  | }  | 
7654  |  |  | 
7655  |  | /**  | 
7656  |  |  * xmlBufferAddHead:  | 
7657  |  |  * @buf:  the buffer  | 
7658  |  |  * @str:  the #xmlChar string  | 
7659  |  |  * @len:  the number of #xmlChar to add  | 
7660  |  |  *  | 
7661  |  |  * Add a string range to the beginning of an XML buffer.  | 
7662  |  |  * if len == -1, the length of @str is recomputed.  | 
7663  |  |  *  | 
7664  |  |  * Returns 0 successful, a positive error code number otherwise  | 
7665  |  |  *         and -1 in case of internal or API error.  | 
7666  |  |  */  | 
7667  |  | int  | 
7668  | 0  | xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) { | 
7669  | 0  |     unsigned int needSize;  | 
7670  |  | 
  | 
7671  | 0  |     if (buf == NULL)  | 
7672  | 0  |         return(-1);  | 
7673  | 0  |     if (str == NULL) { | 
7674  |  | #ifdef DEBUG_BUFFER  | 
7675  |  |         xmlGenericError(xmlGenericErrorContext,  | 
7676  |  |     "xmlBufferAddHead: str == NULL\n");  | 
7677  |  | #endif  | 
7678  | 0  |   return -1;  | 
7679  | 0  |     }  | 
7680  | 0  |     if (len < -1) { | 
7681  |  | #ifdef DEBUG_BUFFER  | 
7682  |  |         xmlGenericError(xmlGenericErrorContext,  | 
7683  |  |     "xmlBufferAddHead: len < 0\n");  | 
7684  |  | #endif  | 
7685  | 0  |   return -1;  | 
7686  | 0  |     }  | 
7687  | 0  |     if (len == 0) return 0;  | 
7688  |  |  | 
7689  | 0  |     if (len < 0)  | 
7690  | 0  |         len = xmlStrlen(str);  | 
7691  |  | 
  | 
7692  | 0  |     if (len <= 0) return -1;  | 
7693  |  |  | 
7694  | 0  |     if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) { | 
7695  | 0  |         size_t start_buf = buf->content - buf->contentIO;  | 
7696  |  | 
  | 
7697  | 0  |   if (start_buf > (unsigned int) len) { | 
7698  |  |       /*  | 
7699  |  |        * We can add it in the space previously shrunk  | 
7700  |  |        */  | 
7701  | 0  |       buf->content -= len;  | 
7702  | 0  |             memmove(&buf->content[0], str, len);  | 
7703  | 0  |       buf->use += len;  | 
7704  | 0  |       buf->size += len;  | 
7705  | 0  |             buf->content[buf->use] = 0;  | 
7706  | 0  |       return(0);  | 
7707  | 0  |   }  | 
7708  | 0  |     }  | 
7709  |  |     /* Note that both buf->size and buf->use can be zero here. */  | 
7710  | 0  |     if ((unsigned) len >= buf->size - buf->use) { | 
7711  | 0  |         if ((unsigned) len >= UINT_MAX - buf->use) { | 
7712  | 0  |             xmlTreeErrMemory("growing buffer past UINT_MAX"); | 
7713  | 0  |             return(-1);  | 
7714  | 0  |         }  | 
7715  | 0  |         needSize = buf->use + len + 1;  | 
7716  | 0  |         if (!xmlBufferResize(buf, needSize)){ | 
7717  | 0  |       xmlTreeErrMemory("growing buffer"); | 
7718  | 0  |             return XML_ERR_NO_MEMORY;  | 
7719  | 0  |         }  | 
7720  | 0  |     }  | 
7721  |  |  | 
7722  | 0  |     memmove(&buf->content[len], &buf->content[0], buf->use);  | 
7723  | 0  |     memmove(&buf->content[0], str, len);  | 
7724  | 0  |     buf->use += len;  | 
7725  | 0  |     buf->content[buf->use] = 0;  | 
7726  | 0  |     return 0;  | 
7727  | 0  | }  | 
7728  |  |  | 
7729  |  | /**  | 
7730  |  |  * xmlBufferCat:  | 
7731  |  |  * @buf:  the buffer to add to  | 
7732  |  |  * @str:  the #xmlChar string  | 
7733  |  |  *  | 
7734  |  |  * Append a zero terminated string to an XML buffer.  | 
7735  |  |  *  | 
7736  |  |  * Returns 0 successful, a positive error code number otherwise  | 
7737  |  |  *         and -1 in case of internal or API error.  | 
7738  |  |  */  | 
7739  |  | int  | 
7740  | 553k  | xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) { | 
7741  | 553k  |     if (buf == NULL)  | 
7742  | 0  |         return(-1);  | 
7743  | 553k  |     if (str == NULL) return -1;  | 
7744  | 553k  |     return xmlBufferAdd(buf, str, -1);  | 
7745  | 553k  | }  | 
7746  |  |  | 
7747  |  | /**  | 
7748  |  |  * xmlBufferCCat:  | 
7749  |  |  * @buf:  the buffer to dump  | 
7750  |  |  * @str:  the C char string  | 
7751  |  |  *  | 
7752  |  |  * Append a zero terminated C string to an XML buffer.  | 
7753  |  |  *  | 
7754  |  |  * Returns 0 successful, a positive error code number otherwise  | 
7755  |  |  *         and -1 in case of internal or API error.  | 
7756  |  |  */  | 
7757  |  | int  | 
7758  | 0  | xmlBufferCCat(xmlBufferPtr buf, const char *str) { | 
7759  | 0  |     return xmlBufferCat(buf, (const xmlChar *) str);  | 
7760  | 0  | }  | 
7761  |  |  | 
7762  |  | /**  | 
7763  |  |  * xmlBufferWriteCHAR:  | 
7764  |  |  * @buf:  the XML buffer  | 
7765  |  |  * @string:  the string to add  | 
7766  |  |  *  | 
7767  |  |  * routine which manages and grows an output buffer. This one adds  | 
7768  |  |  * xmlChars at the end of the buffer.  | 
7769  |  |  */  | 
7770  |  | void  | 
7771  | 0  | xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) { | 
7772  | 0  |     if (buf == NULL)  | 
7773  | 0  |         return;  | 
7774  | 0  |     xmlBufferCat(buf, string);  | 
7775  | 0  | }  | 
7776  |  |  | 
7777  |  | /**  | 
7778  |  |  * xmlBufferWriteChar:  | 
7779  |  |  * @buf:  the XML buffer output  | 
7780  |  |  * @string:  the string to add  | 
7781  |  |  *  | 
7782  |  |  * routine which manage and grows an output buffer. This one add  | 
7783  |  |  * C chars at the end of the array.  | 
7784  |  |  */  | 
7785  |  | void  | 
7786  | 0  | xmlBufferWriteChar(xmlBufferPtr buf, const char *string) { | 
7787  | 0  |     if (buf == NULL)  | 
7788  | 0  |         return;  | 
7789  | 0  |     xmlBufferCCat(buf, string);  | 
7790  | 0  | }  | 
7791  |  |  | 
7792  |  |  | 
7793  |  | /**  | 
7794  |  |  * xmlBufferWriteQuotedString:  | 
7795  |  |  * @buf:  the XML buffer output  | 
7796  |  |  * @string:  the string to add  | 
7797  |  |  *  | 
7798  |  |  * routine which manage and grows an output buffer. This one writes  | 
7799  |  |  * a quoted or double quoted #xmlChar string, checking first if it holds  | 
7800  |  |  * quote or double-quotes internally  | 
7801  |  |  */  | 
7802  |  | void  | 
7803  | 0  | xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) { | 
7804  | 0  |     const xmlChar *cur, *base;  | 
7805  | 0  |     if (buf == NULL)  | 
7806  | 0  |         return;  | 
7807  | 0  |     if (xmlStrchr(string, '\"')) { | 
7808  | 0  |         if (xmlStrchr(string, '\'')) { | 
7809  |  | #ifdef DEBUG_BUFFER  | 
7810  |  |       xmlGenericError(xmlGenericErrorContext,  | 
7811  |  |  "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");  | 
7812  |  | #endif  | 
7813  | 0  |       xmlBufferCCat(buf, "\"");  | 
7814  | 0  |             base = cur = string;  | 
7815  | 0  |             while(*cur != 0){ | 
7816  | 0  |                 if(*cur == '"'){ | 
7817  | 0  |                     if (base != cur)  | 
7818  | 0  |                         xmlBufferAdd(buf, base, cur - base);  | 
7819  | 0  |                     xmlBufferAdd(buf, BAD_CAST """, 6);  | 
7820  | 0  |                     cur++;  | 
7821  | 0  |                     base = cur;  | 
7822  | 0  |                 }  | 
7823  | 0  |                 else { | 
7824  | 0  |                     cur++;  | 
7825  | 0  |                 }  | 
7826  | 0  |             }  | 
7827  | 0  |             if (base != cur)  | 
7828  | 0  |                 xmlBufferAdd(buf, base, cur - base);  | 
7829  | 0  |       xmlBufferCCat(buf, "\"");  | 
7830  | 0  |   }  | 
7831  | 0  |         else{ | 
7832  | 0  |       xmlBufferCCat(buf, "\'");  | 
7833  | 0  |             xmlBufferCat(buf, string);  | 
7834  | 0  |       xmlBufferCCat(buf, "\'");  | 
7835  | 0  |         }  | 
7836  | 0  |     } else { | 
7837  | 0  |         xmlBufferCCat(buf, "\"");  | 
7838  | 0  |         xmlBufferCat(buf, string);  | 
7839  | 0  |         xmlBufferCCat(buf, "\"");  | 
7840  | 0  |     }  | 
7841  | 0  | }  | 
7842  |  |  | 
7843  |  |  | 
7844  |  | /**  | 
7845  |  |  * xmlGetDocCompressMode:  | 
7846  |  |  * @doc:  the document  | 
7847  |  |  *  | 
7848  |  |  * get the compression ratio for a document, ZLIB based  | 
7849  |  |  * Returns 0 (uncompressed) to 9 (max compression)  | 
7850  |  |  */  | 
7851  |  | int  | 
7852  | 0  | xmlGetDocCompressMode (const xmlDoc *doc) { | 
7853  | 0  |     if (doc == NULL) return(-1);  | 
7854  | 0  |     return(doc->compression);  | 
7855  | 0  | }  | 
7856  |  |  | 
7857  |  | /**  | 
7858  |  |  * xmlSetDocCompressMode:  | 
7859  |  |  * @doc:  the document  | 
7860  |  |  * @mode:  the compression ratio  | 
7861  |  |  *  | 
7862  |  |  * set the compression ratio for a document, ZLIB based  | 
7863  |  |  * Correct values: 0 (uncompressed) to 9 (max compression)  | 
7864  |  |  */  | 
7865  |  | void  | 
7866  | 0  | xmlSetDocCompressMode (xmlDocPtr doc, int mode) { | 
7867  | 0  |     if (doc == NULL) return;  | 
7868  | 0  |     if (mode < 0) doc->compression = 0;  | 
7869  | 0  |     else if (mode > 9) doc->compression = 9;  | 
7870  | 0  |     else doc->compression = mode;  | 
7871  | 0  | }  | 
7872  |  |  | 
7873  |  | /**  | 
7874  |  |  * xmlGetCompressMode:  | 
7875  |  |  *  | 
7876  |  |  * get the default compression mode used, ZLIB based.  | 
7877  |  |  * Returns 0 (uncompressed) to 9 (max compression)  | 
7878  |  |  */  | 
7879  |  | int  | 
7880  |  | xmlGetCompressMode(void)  | 
7881  | 0  | { | 
7882  | 0  |     return (xmlCompressMode);  | 
7883  | 0  | }  | 
7884  |  |  | 
7885  |  | /**  | 
7886  |  |  * xmlSetCompressMode:  | 
7887  |  |  * @mode:  the compression ratio  | 
7888  |  |  *  | 
7889  |  |  * set the default compression mode used, ZLIB based  | 
7890  |  |  * Correct values: 0 (uncompressed) to 9 (max compression)  | 
7891  |  |  */  | 
7892  |  | void  | 
7893  | 0  | xmlSetCompressMode(int mode) { | 
7894  | 0  |     if (mode < 0) xmlCompressMode = 0;  | 
7895  | 0  |     else if (mode > 9) xmlCompressMode = 9;  | 
7896  | 0  |     else xmlCompressMode = mode;  | 
7897  | 0  | }  | 
7898  |  |  | 
7899  | 0  | #define XML_TREE_NSMAP_PARENT -1  | 
7900  |  | #define XML_TREE_NSMAP_XML -2  | 
7901  | 0  | #define XML_TREE_NSMAP_DOC -3  | 
7902  | 0  | #define XML_TREE_NSMAP_CUSTOM -4  | 
7903  |  |  | 
7904  |  | typedef struct xmlNsMapItem *xmlNsMapItemPtr;  | 
7905  |  | struct xmlNsMapItem { | 
7906  |  |     xmlNsMapItemPtr next;  | 
7907  |  |     xmlNsMapItemPtr prev;  | 
7908  |  |     xmlNsPtr oldNs; /* old ns decl reference */  | 
7909  |  |     xmlNsPtr newNs; /* new ns decl reference */  | 
7910  |  |     int shadowDepth; /* Shadowed at this depth */  | 
7911  |  |     /*  | 
7912  |  |     * depth:  | 
7913  |  |     * >= 0 == @node's ns-decls  | 
7914  |  |     * -1   == @parent's ns-decls  | 
7915  |  |     * -2   == the doc->oldNs XML ns-decl  | 
7916  |  |     * -3   == the doc->oldNs storage ns-decls  | 
7917  |  |     * -4   == ns-decls provided via custom ns-handling  | 
7918  |  |     */  | 
7919  |  |     int depth;  | 
7920  |  | };  | 
7921  |  |  | 
7922  |  | typedef struct xmlNsMap *xmlNsMapPtr;  | 
7923  |  | struct xmlNsMap { | 
7924  |  |     xmlNsMapItemPtr first;  | 
7925  |  |     xmlNsMapItemPtr last;  | 
7926  |  |     xmlNsMapItemPtr pool;  | 
7927  |  | };  | 
7928  |  |  | 
7929  | 0  | #define XML_NSMAP_NOTEMPTY(m) (((m) != NULL) && ((m)->first != NULL))  | 
7930  | 0  | #define XML_NSMAP_FOREACH(m, i) for (i = (m)->first; i != NULL; i = (i)->next)  | 
7931  |  | #define XML_NSMAP_POP(m, i) \  | 
7932  | 0  |     i = (m)->last; \  | 
7933  | 0  |     (m)->last = (i)->prev; \  | 
7934  | 0  |     if ((m)->last == NULL) \  | 
7935  | 0  |   (m)->first = NULL; \  | 
7936  | 0  |     else \  | 
7937  | 0  |   (m)->last->next = NULL; \  | 
7938  | 0  |     (i)->next = (m)->pool; \  | 
7939  | 0  |     (m)->pool = i;  | 
7940  |  |  | 
7941  |  | /*  | 
7942  |  | * xmlDOMWrapNsMapFree:  | 
7943  |  | * @map: the ns-map  | 
7944  |  | *  | 
7945  |  | * Frees the ns-map  | 
7946  |  | */  | 
7947  |  | static void  | 
7948  |  | xmlDOMWrapNsMapFree(xmlNsMapPtr nsmap)  | 
7949  | 0  | { | 
7950  | 0  |     xmlNsMapItemPtr cur, tmp;  | 
7951  |  | 
  | 
7952  | 0  |     if (nsmap == NULL)  | 
7953  | 0  |   return;  | 
7954  | 0  |     cur = nsmap->pool;  | 
7955  | 0  |     while (cur != NULL) { | 
7956  | 0  |   tmp = cur;  | 
7957  | 0  |   cur = cur->next;  | 
7958  | 0  |   xmlFree(tmp);  | 
7959  | 0  |     }  | 
7960  | 0  |     cur = nsmap->first;  | 
7961  | 0  |     while (cur != NULL) { | 
7962  | 0  |   tmp = cur;  | 
7963  | 0  |   cur = cur->next;  | 
7964  | 0  |   xmlFree(tmp);  | 
7965  | 0  |     }  | 
7966  | 0  |     xmlFree(nsmap);  | 
7967  | 0  | }  | 
7968  |  |  | 
7969  |  | /*  | 
7970  |  | * xmlDOMWrapNsMapAddItem:  | 
7971  |  | * @map: the ns-map  | 
7972  |  | * @oldNs: the old ns-struct  | 
7973  |  | * @newNs: the new ns-struct  | 
7974  |  | * @depth: depth and ns-kind information  | 
7975  |  | *  | 
7976  |  | * Adds an ns-mapping item.  | 
7977  |  | */  | 
7978  |  | static xmlNsMapItemPtr  | 
7979  |  | xmlDOMWrapNsMapAddItem(xmlNsMapPtr *nsmap, int position,  | 
7980  |  |            xmlNsPtr oldNs, xmlNsPtr newNs, int depth)  | 
7981  | 0  | { | 
7982  | 0  |     xmlNsMapItemPtr ret;  | 
7983  | 0  |     xmlNsMapPtr map;  | 
7984  |  | 
  | 
7985  | 0  |     if (nsmap == NULL)  | 
7986  | 0  |   return(NULL);  | 
7987  | 0  |     if ((position != -1) && (position != 0))  | 
7988  | 0  |   return(NULL);  | 
7989  | 0  |     map = *nsmap;  | 
7990  |  | 
  | 
7991  | 0  |     if (map == NULL) { | 
7992  |  |   /*  | 
7993  |  |   * Create the ns-map.  | 
7994  |  |   */  | 
7995  | 0  |   map = (xmlNsMapPtr) xmlMalloc(sizeof(struct xmlNsMap));  | 
7996  | 0  |   if (map == NULL) { | 
7997  | 0  |       xmlTreeErrMemory("allocating namespace map"); | 
7998  | 0  |       return (NULL);  | 
7999  | 0  |   }  | 
8000  | 0  |   memset(map, 0, sizeof(struct xmlNsMap));  | 
8001  | 0  |   *nsmap = map;  | 
8002  | 0  |     }  | 
8003  |  |  | 
8004  | 0  |     if (map->pool != NULL) { | 
8005  |  |   /*  | 
8006  |  |   * Reuse an item from the pool.  | 
8007  |  |   */  | 
8008  | 0  |   ret = map->pool;  | 
8009  | 0  |   map->pool = ret->next;  | 
8010  | 0  |   memset(ret, 0, sizeof(struct xmlNsMapItem));  | 
8011  | 0  |     } else { | 
8012  |  |   /*  | 
8013  |  |   * Create a new item.  | 
8014  |  |   */  | 
8015  | 0  |   ret = (xmlNsMapItemPtr) xmlMalloc(sizeof(struct xmlNsMapItem));  | 
8016  | 0  |   if (ret == NULL) { | 
8017  | 0  |       xmlTreeErrMemory("allocating namespace map item"); | 
8018  | 0  |       return (NULL);  | 
8019  | 0  |   }  | 
8020  | 0  |   memset(ret, 0, sizeof(struct xmlNsMapItem));  | 
8021  | 0  |     }  | 
8022  |  |  | 
8023  | 0  |     if (map->first == NULL) { | 
8024  |  |   /*  | 
8025  |  |   * First ever.  | 
8026  |  |   */  | 
8027  | 0  |   map->first = ret;  | 
8028  | 0  |   map->last = ret;  | 
8029  | 0  |     } else if (position == -1) { | 
8030  |  |   /*  | 
8031  |  |   * Append.  | 
8032  |  |   */  | 
8033  | 0  |   ret->prev = map->last;  | 
8034  | 0  |   map->last->next = ret;  | 
8035  | 0  |   map->last = ret;  | 
8036  | 0  |     } else if (position == 0) { | 
8037  |  |   /*  | 
8038  |  |   * Set on first position.  | 
8039  |  |   */  | 
8040  | 0  |   map->first->prev = ret;  | 
8041  | 0  |   ret->next = map->first;  | 
8042  | 0  |   map->first = ret;  | 
8043  | 0  |     }  | 
8044  |  | 
  | 
8045  | 0  |     ret->oldNs = oldNs;  | 
8046  | 0  |     ret->newNs = newNs;  | 
8047  | 0  |     ret->shadowDepth = -1;  | 
8048  | 0  |     ret->depth = depth;  | 
8049  | 0  |     return (ret);  | 
8050  | 0  | }  | 
8051  |  |  | 
8052  |  | /*  | 
8053  |  | * xmlDOMWrapStoreNs:  | 
8054  |  | * @doc: the doc  | 
8055  |  | * @nsName: the namespace name  | 
8056  |  | * @prefix: the prefix  | 
8057  |  | *  | 
8058  |  | * Creates or reuses an xmlNs struct on doc->oldNs with  | 
8059  |  | * the given prefix and namespace name.  | 
8060  |  | *  | 
8061  |  | * Returns the acquired ns struct or NULL in case of an API  | 
8062  |  | *         or internal error.  | 
8063  |  | */  | 
8064  |  | static xmlNsPtr  | 
8065  |  | xmlDOMWrapStoreNs(xmlDocPtr doc,  | 
8066  |  |        const xmlChar *nsName,  | 
8067  |  |        const xmlChar *prefix)  | 
8068  | 0  | { | 
8069  | 0  |     xmlNsPtr ns;  | 
8070  |  | 
  | 
8071  | 0  |     if (doc == NULL)  | 
8072  | 0  |   return (NULL);  | 
8073  | 0  |     ns = xmlTreeEnsureXMLDecl(doc);  | 
8074  | 0  |     if (ns == NULL)  | 
8075  | 0  |   return (NULL);  | 
8076  | 0  |     if (ns->next != NULL) { | 
8077  |  |   /* Reuse. */  | 
8078  | 0  |   ns = ns->next;  | 
8079  | 0  |   while (ns != NULL) { | 
8080  | 0  |       if (((ns->prefix == prefix) ||  | 
8081  | 0  |     xmlStrEqual(ns->prefix, prefix)) &&  | 
8082  | 0  |     xmlStrEqual(ns->href, nsName)) { | 
8083  | 0  |     return (ns);  | 
8084  | 0  |       }  | 
8085  | 0  |       if (ns->next == NULL)  | 
8086  | 0  |     break;  | 
8087  | 0  |       ns = ns->next;  | 
8088  | 0  |   }  | 
8089  | 0  |     }  | 
8090  |  |     /* Create. */  | 
8091  | 0  |     if (ns != NULL) { | 
8092  | 0  |         ns->next = xmlNewNs(NULL, nsName, prefix);  | 
8093  | 0  |         return (ns->next);  | 
8094  | 0  |     }  | 
8095  | 0  |     return(NULL);  | 
8096  | 0  | }  | 
8097  |  |  | 
8098  |  | /*  | 
8099  |  | * xmlDOMWrapNewCtxt:  | 
8100  |  | *  | 
8101  |  | * Allocates and initializes a new DOM-wrapper context.  | 
8102  |  | *  | 
8103  |  | * Returns the xmlDOMWrapCtxtPtr or NULL in case of an internal error.  | 
8104  |  | */  | 
8105  |  | xmlDOMWrapCtxtPtr  | 
8106  |  | xmlDOMWrapNewCtxt(void)  | 
8107  | 0  | { | 
8108  | 0  |     xmlDOMWrapCtxtPtr ret;  | 
8109  |  | 
  | 
8110  | 0  |     ret = xmlMalloc(sizeof(xmlDOMWrapCtxt));  | 
8111  | 0  |     if (ret == NULL) { | 
8112  | 0  |   xmlTreeErrMemory("allocating DOM-wrapper context"); | 
8113  | 0  |   return (NULL);  | 
8114  | 0  |     }  | 
8115  | 0  |     memset(ret, 0, sizeof(xmlDOMWrapCtxt));  | 
8116  | 0  |     return (ret);  | 
8117  | 0  | }  | 
8118  |  |  | 
8119  |  | /*  | 
8120  |  | * xmlDOMWrapFreeCtxt:  | 
8121  |  | * @ctxt: the DOM-wrapper context  | 
8122  |  | *  | 
8123  |  | * Frees the DOM-wrapper context.  | 
8124  |  | */  | 
8125  |  | void  | 
8126  |  | xmlDOMWrapFreeCtxt(xmlDOMWrapCtxtPtr ctxt)  | 
8127  | 0  | { | 
8128  | 0  |     if (ctxt == NULL)  | 
8129  | 0  |   return;  | 
8130  | 0  |     if (ctxt->namespaceMap != NULL)  | 
8131  | 0  |   xmlDOMWrapNsMapFree((xmlNsMapPtr) ctxt->namespaceMap);  | 
8132  |  |     /*  | 
8133  |  |     * TODO: Store the namespace map in the context.  | 
8134  |  |     */  | 
8135  | 0  |     xmlFree(ctxt);  | 
8136  | 0  | }  | 
8137  |  |  | 
8138  |  | /*  | 
8139  |  | * xmlTreeLookupNsListByPrefix:  | 
8140  |  | * @nsList: a list of ns-structs  | 
8141  |  | * @prefix: the searched prefix  | 
8142  |  | *  | 
8143  |  | * Searches for a ns-decl with the given prefix in @nsList.  | 
8144  |  | *  | 
8145  |  | * Returns the ns-decl if found, NULL if not found and on  | 
8146  |  | *         API errors.  | 
8147  |  | */  | 
8148  |  | static xmlNsPtr  | 
8149  |  | xmlTreeNSListLookupByPrefix(xmlNsPtr nsList, const xmlChar *prefix)  | 
8150  | 0  | { | 
8151  | 0  |     if (nsList == NULL)  | 
8152  | 0  |   return (NULL);  | 
8153  | 0  |     { | 
8154  | 0  |   xmlNsPtr ns;  | 
8155  | 0  |   ns = nsList;  | 
8156  | 0  |   do { | 
8157  | 0  |       if ((prefix == ns->prefix) ||  | 
8158  | 0  |     xmlStrEqual(prefix, ns->prefix)) { | 
8159  | 0  |     return (ns);  | 
8160  | 0  |       }  | 
8161  | 0  |       ns = ns->next;  | 
8162  | 0  |   } while (ns != NULL);  | 
8163  | 0  |     }  | 
8164  | 0  |     return (NULL);  | 
8165  | 0  | }  | 
8166  |  |  | 
8167  |  | /*  | 
8168  |  | *  | 
8169  |  | * xmlDOMWrapNSNormGatherInScopeNs:  | 
8170  |  | * @map: the namespace map  | 
8171  |  | * @node: the node to start with  | 
8172  |  | *  | 
8173  |  | * Puts in-scope namespaces into the ns-map.  | 
8174  |  | *  | 
8175  |  | * Returns 0 on success, -1 on API or internal errors.  | 
8176  |  | */  | 
8177  |  | static int  | 
8178  |  | xmlDOMWrapNSNormGatherInScopeNs(xmlNsMapPtr *map,  | 
8179  |  |         xmlNodePtr node)  | 
8180  | 0  | { | 
8181  | 0  |     xmlNodePtr cur;  | 
8182  | 0  |     xmlNsPtr ns;  | 
8183  | 0  |     xmlNsMapItemPtr mi;  | 
8184  | 0  |     int shadowed;  | 
8185  |  | 
  | 
8186  | 0  |     if ((map == NULL) || (*map != NULL))  | 
8187  | 0  |   return (-1);  | 
8188  | 0  |     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))  | 
8189  | 0  |         return (-1);  | 
8190  |  |     /*  | 
8191  |  |     * Get in-scope ns-decls of @parent.  | 
8192  |  |     */  | 
8193  | 0  |     cur = node;  | 
8194  | 0  |     while ((cur != NULL) && (cur != (xmlNodePtr) cur->doc)) { | 
8195  | 0  |   if (cur->type == XML_ELEMENT_NODE) { | 
8196  | 0  |       if (cur->nsDef != NULL) { | 
8197  | 0  |     ns = cur->nsDef;  | 
8198  | 0  |     do { | 
8199  | 0  |         shadowed = 0;  | 
8200  | 0  |         if (XML_NSMAP_NOTEMPTY(*map)) { | 
8201  |  |       /*  | 
8202  |  |       * Skip shadowed prefixes.  | 
8203  |  |       */  | 
8204  | 0  |       XML_NSMAP_FOREACH(*map, mi) { | 
8205  | 0  |           if ((ns->prefix == mi->newNs->prefix) ||  | 
8206  | 0  |         xmlStrEqual(ns->prefix, mi->newNs->prefix)) { | 
8207  | 0  |         shadowed = 1;  | 
8208  | 0  |         break;  | 
8209  | 0  |           }  | 
8210  | 0  |       }  | 
8211  | 0  |         }  | 
8212  |  |         /*  | 
8213  |  |         * Insert mapping.  | 
8214  |  |         */  | 
8215  | 0  |         mi = xmlDOMWrapNsMapAddItem(map, 0, NULL,  | 
8216  | 0  |       ns, XML_TREE_NSMAP_PARENT);  | 
8217  | 0  |         if (mi == NULL)  | 
8218  | 0  |       return (-1);  | 
8219  | 0  |         if (shadowed)  | 
8220  | 0  |       mi->shadowDepth = 0;  | 
8221  | 0  |         ns = ns->next;  | 
8222  | 0  |     } while (ns != NULL);  | 
8223  | 0  |       }  | 
8224  | 0  |   }  | 
8225  | 0  |   cur = cur->parent;  | 
8226  | 0  |     }  | 
8227  | 0  |     return (0);  | 
8228  | 0  | }  | 
8229  |  |  | 
8230  |  | /*  | 
8231  |  | * XML_TREE_ADOPT_STR: If we have a dest-dict, put @str in the dict;  | 
8232  |  | * otherwise copy it, when it was in the source-dict.  | 
8233  |  | */  | 
8234  |  | #define XML_TREE_ADOPT_STR(str) \  | 
8235  | 0  |     if (adoptStr && (str != NULL)) { \ | 
8236  | 0  |   if (destDoc->dict) { \ | 
8237  | 0  |       const xmlChar *old = str; \  | 
8238  | 0  |       str = xmlDictLookup(destDoc->dict, str, -1); \  | 
8239  | 0  |       if ((sourceDoc == NULL) || (sourceDoc->dict == NULL) || \  | 
8240  | 0  |           (!xmlDictOwns(sourceDoc->dict, old))) \  | 
8241  | 0  |     xmlFree((char *)old); \  | 
8242  | 0  |   } else if ((sourceDoc) && (sourceDoc->dict) && \  | 
8243  | 0  |       xmlDictOwns(sourceDoc->dict, str)) { \ | 
8244  | 0  |       str = BAD_CAST xmlStrdup(str); \  | 
8245  | 0  |   } \  | 
8246  | 0  |     }  | 
8247  |  |  | 
8248  |  | /*  | 
8249  |  | * XML_TREE_ADOPT_STR_2: If @str was in the source-dict, then  | 
8250  |  | * put it in dest-dict or copy it.  | 
8251  |  | */  | 
8252  |  | #define XML_TREE_ADOPT_STR_2(str) \  | 
8253  | 0  |     if (adoptStr && (str != NULL) && (sourceDoc != NULL) && \  | 
8254  | 0  |   (sourceDoc->dict != NULL) && \  | 
8255  | 0  |   xmlDictOwns(sourceDoc->dict, cur->content)) { \ | 
8256  | 0  |   if (destDoc->dict) \  | 
8257  | 0  |       cur->content = (xmlChar *) \  | 
8258  | 0  |     xmlDictLookup(destDoc->dict, cur->content, -1); \  | 
8259  | 0  |   else \  | 
8260  | 0  |       cur->content = xmlStrdup(BAD_CAST cur->content); \  | 
8261  | 0  |     }  | 
8262  |  |  | 
8263  |  | /*  | 
8264  |  | * xmlDOMWrapNSNormAddNsMapItem2:  | 
8265  |  | *  | 
8266  |  | * For internal use. Adds a ns-decl mapping.  | 
8267  |  | *  | 
8268  |  | * Returns 0 on success, -1 on internal errors.  | 
8269  |  | */  | 
8270  |  | static int  | 
8271  |  | xmlDOMWrapNSNormAddNsMapItem2(xmlNsPtr **list, int *size, int *number,  | 
8272  |  |       xmlNsPtr oldNs, xmlNsPtr newNs)  | 
8273  | 0  | { | 
8274  | 0  |     if (*list == NULL) { | 
8275  | 0  |   *list = (xmlNsPtr *) xmlMalloc(6 * sizeof(xmlNsPtr));  | 
8276  | 0  |   if (*list == NULL) { | 
8277  | 0  |       xmlTreeErrMemory("alloc ns map item"); | 
8278  | 0  |       return(-1);  | 
8279  | 0  |   }  | 
8280  | 0  |   *size = 3;  | 
8281  | 0  |   *number = 0;  | 
8282  | 0  |     } else if ((*number) >= (*size)) { | 
8283  | 0  |   *size *= 2;  | 
8284  | 0  |   *list = (xmlNsPtr *) xmlRealloc(*list,  | 
8285  | 0  |       (*size) * 2 * sizeof(xmlNsPtr));  | 
8286  | 0  |   if (*list == NULL) { | 
8287  | 0  |       xmlTreeErrMemory("realloc ns map item"); | 
8288  | 0  |       return(-1);  | 
8289  | 0  |   }  | 
8290  | 0  |     }  | 
8291  | 0  |     (*list)[2 * (*number)] = oldNs;  | 
8292  | 0  |     (*list)[2 * (*number) +1] = newNs;  | 
8293  | 0  |     (*number)++;  | 
8294  | 0  |     return (0);  | 
8295  | 0  | }  | 
8296  |  |  | 
8297  |  | /*  | 
8298  |  | * xmlDOMWrapRemoveNode:  | 
8299  |  | * @ctxt: a DOM wrapper context  | 
8300  |  | * @doc: the doc  | 
8301  |  | * @node: the node to be removed.  | 
8302  |  | * @options: set of options, unused at the moment  | 
8303  |  | *  | 
8304  |  | * Unlinks the given node from its owner.  | 
8305  |  | * This will substitute ns-references to node->nsDef for  | 
8306  |  | * ns-references to doc->oldNs, thus ensuring the removed  | 
8307  |  | * branch to be autark wrt ns-references.  | 
8308  |  | *  | 
8309  |  | * NOTE: This function was not intensively tested.  | 
8310  |  | *  | 
8311  |  | * Returns 0 on success, 1 if the node is not supported,  | 
8312  |  | *         -1 on API and internal errors.  | 
8313  |  | */  | 
8314  |  | int  | 
8315  |  | xmlDOMWrapRemoveNode(xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc,  | 
8316  |  |          xmlNodePtr node, int options ATTRIBUTE_UNUSED)  | 
8317  | 0  | { | 
8318  | 0  |     xmlNsPtr *list = NULL;  | 
8319  | 0  |     int sizeList, nbList, i, j;  | 
8320  | 0  |     xmlNsPtr ns;  | 
8321  |  | 
  | 
8322  | 0  |     if ((node == NULL) || (doc == NULL) || (node->doc != doc))  | 
8323  | 0  |   return (-1);  | 
8324  |  |  | 
8325  |  |     /* TODO: 0 or -1 ? */  | 
8326  | 0  |     if (node->parent == NULL)  | 
8327  | 0  |   return (0);  | 
8328  |  |  | 
8329  | 0  |     switch (node->type) { | 
8330  | 0  |   case XML_TEXT_NODE:  | 
8331  | 0  |   case XML_CDATA_SECTION_NODE:  | 
8332  | 0  |   case XML_ENTITY_REF_NODE:  | 
8333  | 0  |   case XML_PI_NODE:  | 
8334  | 0  |   case XML_COMMENT_NODE:  | 
8335  | 0  |       xmlUnlinkNode(node);  | 
8336  | 0  |       return (0);  | 
8337  | 0  |   case XML_ELEMENT_NODE:  | 
8338  | 0  |   case XML_ATTRIBUTE_NODE:  | 
8339  | 0  |       break;  | 
8340  | 0  |   default:  | 
8341  | 0  |       return (1);  | 
8342  | 0  |     }  | 
8343  | 0  |     xmlUnlinkNode(node);  | 
8344  |  |     /*  | 
8345  |  |     * Save out-of-scope ns-references in doc->oldNs.  | 
8346  |  |     */  | 
8347  | 0  |     do { | 
8348  | 0  |   switch (node->type) { | 
8349  | 0  |       case XML_ELEMENT_NODE:  | 
8350  | 0  |     if ((ctxt == NULL) && (node->nsDef != NULL)) { | 
8351  | 0  |         ns = node->nsDef;  | 
8352  | 0  |         do { | 
8353  | 0  |       if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList,  | 
8354  | 0  |           &nbList, ns, ns) == -1)  | 
8355  | 0  |           goto internal_error;  | 
8356  | 0  |       ns = ns->next;  | 
8357  | 0  |         } while (ns != NULL);  | 
8358  | 0  |     }  | 
8359  |  |                 /* Falls through. */  | 
8360  | 0  |       case XML_ATTRIBUTE_NODE:  | 
8361  | 0  |     if (node->ns != NULL) { | 
8362  |  |         /*  | 
8363  |  |         * Find a mapping.  | 
8364  |  |         */  | 
8365  | 0  |         if (list != NULL) { | 
8366  | 0  |       for (i = 0, j = 0; i < nbList; i++, j += 2) { | 
8367  | 0  |           if (node->ns == list[j]) { | 
8368  | 0  |         node->ns = list[++j];  | 
8369  | 0  |         goto next_node;  | 
8370  | 0  |           }  | 
8371  | 0  |       }  | 
8372  | 0  |         }  | 
8373  | 0  |         ns = NULL;  | 
8374  | 0  |         if (ctxt != NULL) { | 
8375  |  |       /*  | 
8376  |  |       * User defined.  | 
8377  |  |       */  | 
8378  | 0  |         } else { | 
8379  |  |       /*  | 
8380  |  |       * Add to doc's oldNs.  | 
8381  |  |       */  | 
8382  | 0  |       ns = xmlDOMWrapStoreNs(doc, node->ns->href,  | 
8383  | 0  |           node->ns->prefix);  | 
8384  | 0  |       if (ns == NULL)  | 
8385  | 0  |           goto internal_error;  | 
8386  | 0  |         }  | 
8387  | 0  |         if (ns != NULL) { | 
8388  |  |       /*  | 
8389  |  |       * Add mapping.  | 
8390  |  |       */  | 
8391  | 0  |       if (xmlDOMWrapNSNormAddNsMapItem2(&list, &sizeList,  | 
8392  | 0  |           &nbList, node->ns, ns) == -1)  | 
8393  | 0  |           goto internal_error;  | 
8394  | 0  |         }  | 
8395  | 0  |         node->ns = ns;  | 
8396  | 0  |     }  | 
8397  | 0  |     if ((node->type == XML_ELEMENT_NODE) &&  | 
8398  | 0  |         (node->properties != NULL)) { | 
8399  | 0  |         node = (xmlNodePtr) node->properties;  | 
8400  | 0  |         continue;  | 
8401  | 0  |     }  | 
8402  | 0  |     break;  | 
8403  | 0  |       default:  | 
8404  | 0  |     goto next_sibling;  | 
8405  | 0  |   }  | 
8406  | 0  | next_node:  | 
8407  | 0  |   if ((node->type == XML_ELEMENT_NODE) &&  | 
8408  | 0  |       (node->children != NULL)) { | 
8409  | 0  |       node = node->children;  | 
8410  | 0  |       continue;  | 
8411  | 0  |   }  | 
8412  | 0  | next_sibling:  | 
8413  | 0  |   if (node == NULL)  | 
8414  | 0  |       break;  | 
8415  | 0  |   if (node->next != NULL)  | 
8416  | 0  |       node = node->next;  | 
8417  | 0  |   else { | 
8418  | 0  |       node = node->parent;  | 
8419  | 0  |       goto next_sibling;  | 
8420  | 0  |   }  | 
8421  | 0  |     } while (node != NULL);  | 
8422  |  |  | 
8423  | 0  |     if (list != NULL)  | 
8424  | 0  |   xmlFree(list);  | 
8425  | 0  |     return (0);  | 
8426  |  |  | 
8427  | 0  | internal_error:  | 
8428  | 0  |     if (list != NULL)  | 
8429  | 0  |   xmlFree(list);  | 
8430  | 0  |     return (-1);  | 
8431  | 0  | }  | 
8432  |  |  | 
8433  |  | /*  | 
8434  |  | * xmlSearchNsByNamespaceStrict:  | 
8435  |  | * @doc: the document  | 
8436  |  | * @node: the start node  | 
8437  |  | * @nsName: the searched namespace name  | 
8438  |  | * @retNs: the resulting ns-decl  | 
8439  |  | * @prefixed: if the found ns-decl must have a prefix (for attributes)  | 
8440  |  | *  | 
8441  |  | * Dynamically searches for a ns-declaration which matches  | 
8442  |  | * the given @nsName in the ancestor-or-self axis of @node.  | 
8443  |  | *  | 
8444  |  | * Returns 1 if a ns-decl was found, 0 if not and -1 on API  | 
8445  |  | *         and internal errors.  | 
8446  |  | */  | 
8447  |  | static int  | 
8448  |  | xmlSearchNsByNamespaceStrict(xmlDocPtr doc, xmlNodePtr node,  | 
8449  |  |            const xmlChar* nsName,  | 
8450  |  |            xmlNsPtr *retNs, int prefixed)  | 
8451  | 0  | { | 
8452  | 0  |     xmlNodePtr cur, prev = NULL, out = NULL;  | 
8453  | 0  |     xmlNsPtr ns, prevns;  | 
8454  |  | 
  | 
8455  | 0  |     if ((doc == NULL) || (nsName == NULL) || (retNs == NULL))  | 
8456  | 0  |   return (-1);  | 
8457  | 0  |     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))  | 
8458  | 0  |         return(-1);  | 
8459  |  |  | 
8460  | 0  |     *retNs = NULL;  | 
8461  | 0  |     if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) { | 
8462  | 0  |   *retNs = xmlTreeEnsureXMLDecl(doc);  | 
8463  | 0  |   if (*retNs == NULL)  | 
8464  | 0  |       return (-1);  | 
8465  | 0  |   return (1);  | 
8466  | 0  |     }  | 
8467  | 0  |     cur = node;  | 
8468  | 0  |     do { | 
8469  | 0  |   if (cur->type == XML_ELEMENT_NODE) { | 
8470  | 0  |       if (cur->nsDef != NULL) { | 
8471  | 0  |     for (ns = cur->nsDef; ns != NULL; ns = ns->next) { | 
8472  | 0  |         if (prefixed && (ns->prefix == NULL))  | 
8473  | 0  |       continue;  | 
8474  | 0  |         if (prev != NULL) { | 
8475  |  |       /*  | 
8476  |  |       * Check the last level of ns-decls for a  | 
8477  |  |       * shadowing prefix.  | 
8478  |  |       */  | 
8479  | 0  |       prevns = prev->nsDef;  | 
8480  | 0  |       do { | 
8481  | 0  |           if ((prevns->prefix == ns->prefix) ||  | 
8482  | 0  |         ((prevns->prefix != NULL) &&  | 
8483  | 0  |         (ns->prefix != NULL) &&  | 
8484  | 0  |         xmlStrEqual(prevns->prefix, ns->prefix))) { | 
8485  |  |         /*  | 
8486  |  |         * Shadowed.  | 
8487  |  |         */  | 
8488  | 0  |         break;  | 
8489  | 0  |           }  | 
8490  | 0  |           prevns = prevns->next;  | 
8491  | 0  |       } while (prevns != NULL);  | 
8492  | 0  |       if (prevns != NULL)  | 
8493  | 0  |           continue;  | 
8494  | 0  |         }  | 
8495  |  |         /*  | 
8496  |  |         * Ns-name comparison.  | 
8497  |  |         */  | 
8498  | 0  |         if ((nsName == ns->href) ||  | 
8499  | 0  |       xmlStrEqual(nsName, ns->href)) { | 
8500  |  |       /*  | 
8501  |  |       * At this point the prefix can only be shadowed,  | 
8502  |  |       * if we are the the (at least) 3rd level of  | 
8503  |  |       * ns-decls.  | 
8504  |  |       */  | 
8505  | 0  |       if (out) { | 
8506  | 0  |           int ret;  | 
8507  |  | 
  | 
8508  | 0  |           ret = xmlNsInScope(doc, node, prev, ns->prefix);  | 
8509  | 0  |           if (ret < 0)  | 
8510  | 0  |         return (-1);  | 
8511  |  |           /*  | 
8512  |  |           * TODO: Should we try to find a matching ns-name  | 
8513  |  |           * only once? This here keeps on searching.  | 
8514  |  |           * I think we should try further since, there might  | 
8515  |  |           * be an other matching ns-decl with an unshadowed  | 
8516  |  |           * prefix.  | 
8517  |  |           */  | 
8518  | 0  |           if (! ret)  | 
8519  | 0  |         continue;  | 
8520  | 0  |       }  | 
8521  | 0  |       *retNs = ns;  | 
8522  | 0  |       return (1);  | 
8523  | 0  |         }  | 
8524  | 0  |     }  | 
8525  | 0  |     out = prev;  | 
8526  | 0  |     prev = cur;  | 
8527  | 0  |       }  | 
8528  | 0  |   } else if ((cur->type == XML_ENTITY_NODE) ||  | 
8529  | 0  |             (cur->type == XML_ENTITY_DECL))  | 
8530  | 0  |       return (0);  | 
8531  | 0  |   cur = cur->parent;  | 
8532  | 0  |     } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));  | 
8533  | 0  |     return (0);  | 
8534  | 0  | }  | 
8535  |  |  | 
8536  |  | /*  | 
8537  |  | * xmlSearchNsByPrefixStrict:  | 
8538  |  | * @doc: the document  | 
8539  |  | * @node: the start node  | 
8540  |  | * @prefix: the searched namespace prefix  | 
8541  |  | * @retNs: the resulting ns-decl  | 
8542  |  | *  | 
8543  |  | * Dynamically searches for a ns-declaration which matches  | 
8544  |  | * the given @nsName in the ancestor-or-self axis of @node.  | 
8545  |  | *  | 
8546  |  | * Returns 1 if a ns-decl was found, 0 if not and -1 on API  | 
8547  |  | *         and internal errors.  | 
8548  |  | */  | 
8549  |  | static int  | 
8550  |  | xmlSearchNsByPrefixStrict(xmlDocPtr doc, xmlNodePtr node,  | 
8551  |  |         const xmlChar* prefix,  | 
8552  |  |         xmlNsPtr *retNs)  | 
8553  | 0  | { | 
8554  | 0  |     xmlNodePtr cur;  | 
8555  | 0  |     xmlNsPtr ns;  | 
8556  |  | 
  | 
8557  | 0  |     if ((doc == NULL) || (node == NULL) || (node->type == XML_NAMESPACE_DECL))  | 
8558  | 0  |         return(-1);  | 
8559  |  |  | 
8560  | 0  |     if (retNs)  | 
8561  | 0  |   *retNs = NULL;  | 
8562  | 0  |     if (IS_STR_XML(prefix)) { | 
8563  | 0  |   if (retNs) { | 
8564  | 0  |       *retNs = xmlTreeEnsureXMLDecl(doc);  | 
8565  | 0  |       if (*retNs == NULL)  | 
8566  | 0  |     return (-1);  | 
8567  | 0  |   }  | 
8568  | 0  |   return (1);  | 
8569  | 0  |     }  | 
8570  | 0  |     cur = node;  | 
8571  | 0  |     do { | 
8572  | 0  |   if (cur->type == XML_ELEMENT_NODE) { | 
8573  | 0  |       if (cur->nsDef != NULL) { | 
8574  | 0  |     ns = cur->nsDef;  | 
8575  | 0  |     do { | 
8576  | 0  |         if ((prefix == ns->prefix) ||  | 
8577  | 0  |       xmlStrEqual(prefix, ns->prefix))  | 
8578  | 0  |         { | 
8579  |  |       /*  | 
8580  |  |       * Disabled namespaces, e.g. xmlns:abc="".  | 
8581  |  |       */  | 
8582  | 0  |       if (ns->href == NULL)  | 
8583  | 0  |           return(0);  | 
8584  | 0  |       if (retNs)  | 
8585  | 0  |           *retNs = ns;  | 
8586  | 0  |       return (1);  | 
8587  | 0  |         }  | 
8588  | 0  |         ns = ns->next;  | 
8589  | 0  |     } while (ns != NULL);  | 
8590  | 0  |       }  | 
8591  | 0  |   } else if ((cur->type == XML_ENTITY_NODE) ||  | 
8592  | 0  |             (cur->type == XML_ENTITY_DECL))  | 
8593  | 0  |       return (0);  | 
8594  | 0  |   cur = cur->parent;  | 
8595  | 0  |     } while ((cur != NULL) && (cur->doc != (xmlDocPtr) cur));  | 
8596  | 0  |     return (0);  | 
8597  | 0  | }  | 
8598  |  |  | 
8599  |  | /*  | 
8600  |  | * xmlDOMWrapNSNormDeclareNsForced:  | 
8601  |  | * @doc: the doc  | 
8602  |  | * @elem: the element-node to declare on  | 
8603  |  | * @nsName: the namespace-name of the ns-decl  | 
8604  |  | * @prefix: the preferred prefix of the ns-decl  | 
8605  |  | * @checkShadow: ensure that the new ns-decl doesn't shadow ancestor ns-decls  | 
8606  |  | *  | 
8607  |  | * Declares a new namespace on @elem. It tries to use the  | 
8608  |  | * given @prefix; if a ns-decl with the given prefix is already existent  | 
8609  |  | * on @elem, it will generate an other prefix.  | 
8610  |  | *  | 
8611  |  | * Returns 1 if a ns-decl was found, 0 if not and -1 on API  | 
8612  |  | *         and internal errors.  | 
8613  |  | */  | 
8614  |  | static xmlNsPtr  | 
8615  |  | xmlDOMWrapNSNormDeclareNsForced(xmlDocPtr doc,  | 
8616  |  |         xmlNodePtr elem,  | 
8617  |  |         const xmlChar *nsName,  | 
8618  |  |         const xmlChar *prefix,  | 
8619  |  |         int checkShadow)  | 
8620  | 0  | { | 
8621  |  | 
  | 
8622  | 0  |     xmlNsPtr ret;  | 
8623  | 0  |     char buf[50];  | 
8624  | 0  |     const xmlChar *pref;  | 
8625  | 0  |     int counter = 0;  | 
8626  |  | 
  | 
8627  | 0  |     if ((doc == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))  | 
8628  | 0  |         return(NULL);  | 
8629  |  |     /*  | 
8630  |  |     * Create a ns-decl on @anchor.  | 
8631  |  |     */  | 
8632  | 0  |     pref = prefix;  | 
8633  | 0  |     while (1) { | 
8634  |  |   /*  | 
8635  |  |   * Lookup whether the prefix is unused in elem's ns-decls.  | 
8636  |  |   */  | 
8637  | 0  |   if ((elem->nsDef != NULL) &&  | 
8638  | 0  |       (xmlTreeNSListLookupByPrefix(elem->nsDef, pref) != NULL))  | 
8639  | 0  |       goto ns_next_prefix;  | 
8640  | 0  |   if (checkShadow && elem->parent &&  | 
8641  | 0  |       ((xmlNodePtr) elem->parent->doc != elem->parent)) { | 
8642  |  |       /*  | 
8643  |  |       * Does it shadow ancestor ns-decls?  | 
8644  |  |       */  | 
8645  | 0  |       if (xmlSearchNsByPrefixStrict(doc, elem->parent, pref, NULL) == 1)  | 
8646  | 0  |     goto ns_next_prefix;  | 
8647  | 0  |   }  | 
8648  | 0  |   ret = xmlNewNs(NULL, nsName, pref);  | 
8649  | 0  |   if (ret == NULL)  | 
8650  | 0  |       return (NULL);  | 
8651  | 0  |   if (elem->nsDef == NULL)  | 
8652  | 0  |       elem->nsDef = ret;  | 
8653  | 0  |   else { | 
8654  | 0  |       xmlNsPtr ns2 = elem->nsDef;  | 
8655  | 0  |       while (ns2->next != NULL)  | 
8656  | 0  |     ns2 = ns2->next;  | 
8657  | 0  |       ns2->next = ret;  | 
8658  | 0  |   }  | 
8659  | 0  |   return (ret);  | 
8660  | 0  | ns_next_prefix:  | 
8661  | 0  |   counter++;  | 
8662  | 0  |   if (counter > 1000)  | 
8663  | 0  |       return (NULL);  | 
8664  | 0  |   if (prefix == NULL) { | 
8665  | 0  |       snprintf((char *) buf, sizeof(buf),  | 
8666  | 0  |     "ns_%d", counter);  | 
8667  | 0  |   } else  | 
8668  | 0  |       snprintf((char *) buf, sizeof(buf),  | 
8669  | 0  |       "%.30s_%d", (char *)prefix, counter);  | 
8670  | 0  |   pref = BAD_CAST buf;  | 
8671  | 0  |     }  | 
8672  | 0  | }  | 
8673  |  |  | 
8674  |  | /*  | 
8675  |  | * xmlDOMWrapNSNormAcquireNormalizedNs:  | 
8676  |  | * @doc: the doc  | 
8677  |  | * @elem: the element-node to declare namespaces on  | 
8678  |  | * @ns: the ns-struct to use for the search  | 
8679  |  | * @retNs: the found/created ns-struct  | 
8680  |  | * @nsMap: the ns-map  | 
8681  |  | * @depth: the current tree depth  | 
8682  |  | * @ancestorsOnly: search in ancestor ns-decls only  | 
8683  |  | * @prefixed: if the searched ns-decl must have a prefix (for attributes)  | 
8684  |  | *  | 
8685  |  | * Searches for a matching ns-name in the ns-decls of @nsMap, if not  | 
8686  |  | * found it will either declare it on @elem, or store it in doc->oldNs.  | 
8687  |  | * If a new ns-decl needs to be declared on @elem, it tries to use the  | 
8688  |  | * @ns->prefix for it, if this prefix is already in use on @elem, it will  | 
8689  |  | * change the prefix or the new ns-decl.  | 
8690  |  | *  | 
8691  |  | * Returns 0 if succeeded, -1 otherwise and on API/internal errors.  | 
8692  |  | */  | 
8693  |  | static int  | 
8694  |  | xmlDOMWrapNSNormAcquireNormalizedNs(xmlDocPtr doc,  | 
8695  |  |            xmlNodePtr elem,  | 
8696  |  |            xmlNsPtr ns,  | 
8697  |  |            xmlNsPtr *retNs,  | 
8698  |  |            xmlNsMapPtr *nsMap,  | 
8699  |  |  | 
8700  |  |            int depth,  | 
8701  |  |            int ancestorsOnly,  | 
8702  |  |            int prefixed)  | 
8703  | 0  | { | 
8704  | 0  |     xmlNsMapItemPtr mi;  | 
8705  |  | 
  | 
8706  | 0  |     if ((doc == NULL) || (ns == NULL) || (retNs == NULL) ||  | 
8707  | 0  |   (nsMap == NULL))  | 
8708  | 0  |   return (-1);  | 
8709  |  |  | 
8710  | 0  |     *retNs = NULL;  | 
8711  |  |     /*  | 
8712  |  |     * Handle XML namespace.  | 
8713  |  |     */  | 
8714  | 0  |     if (IS_STR_XML(ns->prefix)) { | 
8715  |  |   /*  | 
8716  |  |   * Insert XML namespace mapping.  | 
8717  |  |   */  | 
8718  | 0  |   *retNs = xmlTreeEnsureXMLDecl(doc);  | 
8719  | 0  |   if (*retNs == NULL)  | 
8720  | 0  |       return (-1);  | 
8721  | 0  |   return (0);  | 
8722  | 0  |     }  | 
8723  |  |     /*  | 
8724  |  |     * If the search should be done in ancestors only and no  | 
8725  |  |     * @elem (the first ancestor) was specified, then skip the search.  | 
8726  |  |     */  | 
8727  | 0  |     if ((XML_NSMAP_NOTEMPTY(*nsMap)) &&  | 
8728  | 0  |   (! (ancestorsOnly && (elem == NULL))))  | 
8729  | 0  |     { | 
8730  |  |   /*  | 
8731  |  |   * Try to find an equal ns-name in in-scope ns-decls.  | 
8732  |  |   */  | 
8733  | 0  |   XML_NSMAP_FOREACH(*nsMap, mi) { | 
8734  | 0  |       if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&  | 
8735  |  |     /*  | 
8736  |  |     * ancestorsOnly: This should be turned on to gain speed,  | 
8737  |  |     * if one knows that the branch itself was already  | 
8738  |  |     * ns-wellformed and no stale references existed.  | 
8739  |  |     * I.e. it searches in the ancestor axis only.  | 
8740  |  |     */  | 
8741  | 0  |     ((! ancestorsOnly) || (mi->depth == XML_TREE_NSMAP_PARENT)) &&  | 
8742  |  |     /* Skip shadowed prefixes. */  | 
8743  | 0  |     (mi->shadowDepth == -1) &&  | 
8744  |  |     /* Skip xmlns="" or xmlns:foo="". */  | 
8745  | 0  |     ((mi->newNs->href != NULL) &&  | 
8746  | 0  |     (mi->newNs->href[0] != 0)) &&  | 
8747  |  |     /* Ensure a prefix if wanted. */  | 
8748  | 0  |     ((! prefixed) || (mi->newNs->prefix != NULL)) &&  | 
8749  |  |     /* Equal ns name */  | 
8750  | 0  |     ((mi->newNs->href == ns->href) ||  | 
8751  | 0  |     xmlStrEqual(mi->newNs->href, ns->href))) { | 
8752  |  |     /* Set the mapping. */  | 
8753  | 0  |     mi->oldNs = ns;  | 
8754  | 0  |     *retNs = mi->newNs;  | 
8755  | 0  |     return (0);  | 
8756  | 0  |       }  | 
8757  | 0  |   }  | 
8758  | 0  |     }  | 
8759  |  |     /*  | 
8760  |  |     * No luck, the namespace is out of scope or shadowed.  | 
8761  |  |     */  | 
8762  | 0  |     if (elem == NULL) { | 
8763  | 0  |   xmlNsPtr tmpns;  | 
8764  |  |  | 
8765  |  |   /*  | 
8766  |  |   * Store ns-decls in "oldNs" of the document-node.  | 
8767  |  |   */  | 
8768  | 0  |   tmpns = xmlDOMWrapStoreNs(doc, ns->href, ns->prefix);  | 
8769  | 0  |   if (tmpns == NULL)  | 
8770  | 0  |       return (-1);  | 
8771  |  |   /*  | 
8772  |  |   * Insert mapping.  | 
8773  |  |   */  | 
8774  | 0  |   if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns,  | 
8775  | 0  |     tmpns, XML_TREE_NSMAP_DOC) == NULL) { | 
8776  | 0  |       xmlFreeNs(tmpns);  | 
8777  | 0  |       return (-1);  | 
8778  | 0  |   }  | 
8779  | 0  |   *retNs = tmpns;  | 
8780  | 0  |     } else { | 
8781  | 0  |   xmlNsPtr tmpns;  | 
8782  |  | 
  | 
8783  | 0  |   tmpns = xmlDOMWrapNSNormDeclareNsForced(doc, elem, ns->href,  | 
8784  | 0  |       ns->prefix, 0);  | 
8785  | 0  |   if (tmpns == NULL)  | 
8786  | 0  |       return (-1);  | 
8787  |  |  | 
8788  | 0  |   if (*nsMap != NULL) { | 
8789  |  |       /*  | 
8790  |  |       * Does it shadow ancestor ns-decls?  | 
8791  |  |       */  | 
8792  | 0  |       XML_NSMAP_FOREACH(*nsMap, mi) { | 
8793  | 0  |     if ((mi->depth < depth) &&  | 
8794  | 0  |         (mi->shadowDepth == -1) &&  | 
8795  | 0  |         ((ns->prefix == mi->newNs->prefix) ||  | 
8796  | 0  |         xmlStrEqual(ns->prefix, mi->newNs->prefix))) { | 
8797  |  |         /*  | 
8798  |  |         * Shadows.  | 
8799  |  |         */  | 
8800  | 0  |         mi->shadowDepth = depth;  | 
8801  | 0  |         break;  | 
8802  | 0  |     }  | 
8803  | 0  |       }  | 
8804  | 0  |   }  | 
8805  | 0  |   if (xmlDOMWrapNsMapAddItem(nsMap, -1, ns, tmpns, depth) == NULL) { | 
8806  | 0  |       xmlFreeNs(tmpns);  | 
8807  | 0  |       return (-1);  | 
8808  | 0  |   }  | 
8809  | 0  |   *retNs = tmpns;  | 
8810  | 0  |     }  | 
8811  | 0  |     return (0);  | 
8812  | 0  | }  | 
8813  |  |  | 
8814  |  | typedef enum { | 
8815  |  |     XML_DOM_RECONNS_REMOVEREDUND = 1<<0  | 
8816  |  | } xmlDOMReconcileNSOptions;  | 
8817  |  |  | 
8818  |  | /*  | 
8819  |  | * xmlDOMWrapReconcileNamespaces:  | 
8820  |  | * @ctxt: DOM wrapper context, unused at the moment  | 
8821  |  | * @elem: the element-node  | 
8822  |  | * @options: option flags  | 
8823  |  | *  | 
8824  |  | * Ensures that ns-references point to ns-decls hold on element-nodes.  | 
8825  |  | * Ensures that the tree is namespace wellformed by creating additional  | 
8826  |  | * ns-decls where needed. Note that, since prefixes of already existent  | 
8827  |  | * ns-decls can be shadowed by this process, it could break QNames in  | 
8828  |  | * attribute values or element content.  | 
8829  |  | *  | 
8830  |  | * NOTE: This function was not intensively tested.  | 
8831  |  | *  | 
8832  |  | * Returns 0 if succeeded, -1 otherwise and on API/internal errors.  | 
8833  |  | */  | 
8834  |  |  | 
8835  |  | int  | 
8836  |  | xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt ATTRIBUTE_UNUSED,  | 
8837  |  |             xmlNodePtr elem,  | 
8838  |  |             int options)  | 
8839  | 0  | { | 
8840  | 0  |     int depth = -1, adoptns = 0, parnsdone = 0;  | 
8841  | 0  |     xmlNsPtr ns, prevns;  | 
8842  | 0  |     xmlDocPtr doc;  | 
8843  | 0  |     xmlNodePtr cur, curElem = NULL;  | 
8844  | 0  |     xmlNsMapPtr nsMap = NULL;  | 
8845  | 0  |     xmlNsMapItemPtr /* topmi = NULL, */ mi;  | 
8846  |  |     /* @ancestorsOnly should be set by an option flag. */  | 
8847  | 0  |     int ancestorsOnly = 0;  | 
8848  | 0  |     int optRemoveRedundantNS =  | 
8849  | 0  |   ((xmlDOMReconcileNSOptions) options & XML_DOM_RECONNS_REMOVEREDUND) ? 1 : 0;  | 
8850  | 0  |     xmlNsPtr *listRedund = NULL;  | 
8851  | 0  |     int sizeRedund = 0, nbRedund = 0, ret, i, j;  | 
8852  |  | 
  | 
8853  | 0  |     if ((elem == NULL) || (elem->doc == NULL) ||  | 
8854  | 0  |   (elem->type != XML_ELEMENT_NODE))  | 
8855  | 0  |   return (-1);  | 
8856  |  |  | 
8857  | 0  |     doc = elem->doc;  | 
8858  | 0  |     cur = elem;  | 
8859  | 0  |     do { | 
8860  | 0  |   switch (cur->type) { | 
8861  | 0  |       case XML_ELEMENT_NODE:  | 
8862  | 0  |     adoptns = 1;  | 
8863  | 0  |     curElem = cur;  | 
8864  | 0  |     depth++;  | 
8865  |  |     /*  | 
8866  |  |     * Namespace declarations.  | 
8867  |  |     */  | 
8868  | 0  |     if (cur->nsDef != NULL) { | 
8869  | 0  |         prevns = NULL;  | 
8870  | 0  |         ns = cur->nsDef;  | 
8871  | 0  |         while (ns != NULL) { | 
8872  | 0  |       if (! parnsdone) { | 
8873  | 0  |           if ((elem->parent) &&  | 
8874  | 0  |         ((xmlNodePtr) elem->parent->doc != elem->parent)) { | 
8875  |  |         /*  | 
8876  |  |         * Gather ancestor in-scope ns-decls.  | 
8877  |  |         */  | 
8878  | 0  |         if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,  | 
8879  | 0  |             elem->parent) == -1)  | 
8880  | 0  |             goto internal_error;  | 
8881  | 0  |           }  | 
8882  | 0  |           parnsdone = 1;  | 
8883  | 0  |       }  | 
8884  |  |  | 
8885  |  |       /*  | 
8886  |  |       * Lookup the ns ancestor-axis for equal ns-decls in scope.  | 
8887  |  |       */  | 
8888  | 0  |       if (optRemoveRedundantNS && XML_NSMAP_NOTEMPTY(nsMap)) { | 
8889  | 0  |           XML_NSMAP_FOREACH(nsMap, mi) { | 
8890  | 0  |         if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&  | 
8891  | 0  |             (mi->shadowDepth == -1) &&  | 
8892  | 0  |             ((ns->prefix == mi->newNs->prefix) ||  | 
8893  | 0  |               xmlStrEqual(ns->prefix, mi->newNs->prefix)) &&  | 
8894  | 0  |             ((ns->href == mi->newNs->href) ||  | 
8895  | 0  |               xmlStrEqual(ns->href, mi->newNs->href)))  | 
8896  | 0  |         { | 
8897  |  |             /*  | 
8898  |  |             * A redundant ns-decl was found.  | 
8899  |  |             * Add it to the list of redundant ns-decls.  | 
8900  |  |             */  | 
8901  | 0  |             if (xmlDOMWrapNSNormAddNsMapItem2(&listRedund,  | 
8902  | 0  |           &sizeRedund, &nbRedund, ns, mi->newNs) == -1)  | 
8903  | 0  |           goto internal_error;  | 
8904  |  |             /*  | 
8905  |  |             * Remove the ns-decl from the element-node.  | 
8906  |  |             */  | 
8907  | 0  |             if (prevns)  | 
8908  | 0  |           prevns->next = ns->next;  | 
8909  | 0  |             else  | 
8910  | 0  |           cur->nsDef = ns->next;  | 
8911  | 0  |             goto next_ns_decl;  | 
8912  | 0  |         }  | 
8913  | 0  |           }  | 
8914  | 0  |       }  | 
8915  |  |  | 
8916  |  |       /*  | 
8917  |  |       * Skip ns-references handling if the referenced  | 
8918  |  |       * ns-decl is declared on the same element.  | 
8919  |  |       */  | 
8920  | 0  |       if ((cur->ns != NULL) && adoptns && (cur->ns == ns))  | 
8921  | 0  |           adoptns = 0;  | 
8922  |  |       /*  | 
8923  |  |       * Does it shadow any ns-decl?  | 
8924  |  |       */  | 
8925  | 0  |       if (XML_NSMAP_NOTEMPTY(nsMap)) { | 
8926  | 0  |           XML_NSMAP_FOREACH(nsMap, mi) { | 
8927  | 0  |         if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&  | 
8928  | 0  |             (mi->shadowDepth == -1) &&  | 
8929  | 0  |             ((ns->prefix == mi->newNs->prefix) ||  | 
8930  | 0  |             xmlStrEqual(ns->prefix, mi->newNs->prefix))) { | 
8931  |  | 
  | 
8932  | 0  |             mi->shadowDepth = depth;  | 
8933  | 0  |         }  | 
8934  | 0  |           }  | 
8935  | 0  |       }  | 
8936  |  |       /*  | 
8937  |  |       * Push mapping.  | 
8938  |  |       */  | 
8939  | 0  |       if (xmlDOMWrapNsMapAddItem(&nsMap, -1, ns, ns,  | 
8940  | 0  |           depth) == NULL)  | 
8941  | 0  |           goto internal_error;  | 
8942  |  |  | 
8943  | 0  |       prevns = ns;  | 
8944  | 0  | next_ns_decl:  | 
8945  | 0  |       ns = ns->next;  | 
8946  | 0  |         }  | 
8947  | 0  |     }  | 
8948  | 0  |     if (! adoptns)  | 
8949  | 0  |         goto ns_end;  | 
8950  |  |                 /* Falls through. */  | 
8951  | 0  |       case XML_ATTRIBUTE_NODE:  | 
8952  |  |     /* No ns, no fun. */  | 
8953  | 0  |     if (cur->ns == NULL)  | 
8954  | 0  |         goto ns_end;  | 
8955  |  |  | 
8956  | 0  |     if (! parnsdone) { | 
8957  | 0  |         if ((elem->parent) &&  | 
8958  | 0  |       ((xmlNodePtr) elem->parent->doc != elem->parent)) { | 
8959  | 0  |       if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,  | 
8960  | 0  |         elem->parent) == -1)  | 
8961  | 0  |           goto internal_error;  | 
8962  | 0  |         }  | 
8963  | 0  |         parnsdone = 1;  | 
8964  | 0  |     }  | 
8965  |  |     /*  | 
8966  |  |     * Adjust the reference if this was a redundant ns-decl.  | 
8967  |  |     */  | 
8968  | 0  |     if (listRedund) { | 
8969  | 0  |        for (i = 0, j = 0; i < nbRedund; i++, j += 2) { | 
8970  | 0  |            if (cur->ns == listRedund[j]) { | 
8971  | 0  |          cur->ns = listRedund[++j];  | 
8972  | 0  |          break;  | 
8973  | 0  |            }  | 
8974  | 0  |        }  | 
8975  | 0  |     }  | 
8976  |  |     /*  | 
8977  |  |     * Adopt ns-references.  | 
8978  |  |     */  | 
8979  | 0  |     if (XML_NSMAP_NOTEMPTY(nsMap)) { | 
8980  |  |         /*  | 
8981  |  |         * Search for a mapping.  | 
8982  |  |         */  | 
8983  | 0  |         XML_NSMAP_FOREACH(nsMap, mi) { | 
8984  | 0  |       if ((mi->shadowDepth == -1) &&  | 
8985  | 0  |           (cur->ns == mi->oldNs)) { | 
8986  |  | 
  | 
8987  | 0  |           cur->ns = mi->newNs;  | 
8988  | 0  |           goto ns_end;  | 
8989  | 0  |       }  | 
8990  | 0  |         }  | 
8991  | 0  |     }  | 
8992  |  |     /*  | 
8993  |  |     * Acquire a normalized ns-decl and add it to the map.  | 
8994  |  |     */  | 
8995  | 0  |     if (xmlDOMWrapNSNormAcquireNormalizedNs(doc, curElem,  | 
8996  | 0  |       cur->ns, &ns,  | 
8997  | 0  |       &nsMap, depth,  | 
8998  | 0  |       ancestorsOnly,  | 
8999  | 0  |       (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)  | 
9000  | 0  |         goto internal_error;  | 
9001  | 0  |     cur->ns = ns;  | 
9002  |  | 
  | 
9003  | 0  | ns_end:  | 
9004  | 0  |     if ((cur->type == XML_ELEMENT_NODE) &&  | 
9005  | 0  |         (cur->properties != NULL)) { | 
9006  |  |         /*  | 
9007  |  |         * Process attributes.  | 
9008  |  |         */  | 
9009  | 0  |         cur = (xmlNodePtr) cur->properties;  | 
9010  | 0  |         continue;  | 
9011  | 0  |     }  | 
9012  | 0  |     break;  | 
9013  | 0  |       default:  | 
9014  | 0  |     goto next_sibling;  | 
9015  | 0  |   }  | 
9016  | 0  | into_content:  | 
9017  | 0  |   if ((cur->type == XML_ELEMENT_NODE) &&  | 
9018  | 0  |       (cur->children != NULL)) { | 
9019  |  |       /*  | 
9020  |  |       * Process content of element-nodes only.  | 
9021  |  |       */  | 
9022  | 0  |       cur = cur->children;  | 
9023  | 0  |       continue;  | 
9024  | 0  |   }  | 
9025  | 0  | next_sibling:  | 
9026  | 0  |   if (cur == elem)  | 
9027  | 0  |       break;  | 
9028  | 0  |   if (cur->type == XML_ELEMENT_NODE) { | 
9029  | 0  |       if (XML_NSMAP_NOTEMPTY(nsMap)) { | 
9030  |  |     /*  | 
9031  |  |     * Pop mappings.  | 
9032  |  |     */  | 
9033  | 0  |     while ((nsMap->last != NULL) &&  | 
9034  | 0  |         (nsMap->last->depth >= depth))  | 
9035  | 0  |     { | 
9036  | 0  |         XML_NSMAP_POP(nsMap, mi)  | 
9037  | 0  |     }  | 
9038  |  |     /*  | 
9039  |  |     * Unshadow.  | 
9040  |  |     */  | 
9041  | 0  |     XML_NSMAP_FOREACH(nsMap, mi) { | 
9042  | 0  |         if (mi->shadowDepth >= depth)  | 
9043  | 0  |       mi->shadowDepth = -1;  | 
9044  | 0  |     }  | 
9045  | 0  |       }  | 
9046  | 0  |       depth--;  | 
9047  | 0  |   }  | 
9048  | 0  |   if (cur->next != NULL)  | 
9049  | 0  |       cur = cur->next;  | 
9050  | 0  |   else { | 
9051  | 0  |       if (cur->type == XML_ATTRIBUTE_NODE) { | 
9052  | 0  |     cur = cur->parent;  | 
9053  | 0  |     goto into_content;  | 
9054  | 0  |       }  | 
9055  | 0  |       cur = cur->parent;  | 
9056  | 0  |       goto next_sibling;  | 
9057  | 0  |   }  | 
9058  | 0  |     } while (cur != NULL);  | 
9059  |  |  | 
9060  | 0  |     ret = 0;  | 
9061  | 0  |     goto exit;  | 
9062  | 0  | internal_error:  | 
9063  | 0  |     ret = -1;  | 
9064  | 0  | exit:  | 
9065  | 0  |     if (listRedund) { | 
9066  | 0  |   for (i = 0, j = 0; i < nbRedund; i++, j += 2) { | 
9067  | 0  |       xmlFreeNs(listRedund[j]);  | 
9068  | 0  |   }  | 
9069  | 0  |   xmlFree(listRedund);  | 
9070  | 0  |     }  | 
9071  | 0  |     if (nsMap != NULL)  | 
9072  | 0  |   xmlDOMWrapNsMapFree(nsMap);  | 
9073  | 0  |     return (ret);  | 
9074  | 0  | }  | 
9075  |  |  | 
9076  |  | /*  | 
9077  |  | * xmlDOMWrapAdoptBranch:  | 
9078  |  | * @ctxt: the optional context for custom processing  | 
9079  |  | * @sourceDoc: the optional sourceDoc  | 
9080  |  | * @node: the element-node to start with  | 
9081  |  | * @destDoc: the destination doc for adoption  | 
9082  |  | * @destParent: the optional new parent of @node in @destDoc  | 
9083  |  | * @options: option flags  | 
9084  |  | *  | 
9085  |  | * Ensures that ns-references point to @destDoc: either to  | 
9086  |  | * elements->nsDef entries if @destParent is given, or to  | 
9087  |  | * @destDoc->oldNs otherwise.  | 
9088  |  | * If @destParent is given, it ensures that the tree is namespace  | 
9089  |  | * wellformed by creating additional ns-decls where needed.  | 
9090  |  | * Note that, since prefixes of already existent ns-decls can be  | 
9091  |  | * shadowed by this process, it could break QNames in attribute  | 
9092  |  | * values or element content.  | 
9093  |  | *  | 
9094  |  | * NOTE: This function was not intensively tested.  | 
9095  |  | *  | 
9096  |  | * Returns 0 if succeeded, -1 otherwise and on API/internal errors.  | 
9097  |  | */  | 
9098  |  | static int  | 
9099  |  | xmlDOMWrapAdoptBranch(xmlDOMWrapCtxtPtr ctxt,  | 
9100  |  |           xmlDocPtr sourceDoc,  | 
9101  |  |           xmlNodePtr node,  | 
9102  |  |           xmlDocPtr destDoc,  | 
9103  |  |           xmlNodePtr destParent,  | 
9104  |  |           int options ATTRIBUTE_UNUSED)  | 
9105  | 0  | { | 
9106  | 0  |     int ret = 0;  | 
9107  | 0  |     xmlNodePtr cur, curElem = NULL;  | 
9108  | 0  |     xmlNsMapPtr nsMap = NULL;  | 
9109  | 0  |     xmlNsMapItemPtr mi;  | 
9110  | 0  |     xmlNsPtr ns = NULL;  | 
9111  | 0  |     int depth = -1, adoptStr = 1;  | 
9112  |  |     /* gather @parent's ns-decls. */  | 
9113  | 0  |     int parnsdone;  | 
9114  |  |     /* @ancestorsOnly should be set per option. */  | 
9115  | 0  |     int ancestorsOnly = 0;  | 
9116  |  |  | 
9117  |  |     /*  | 
9118  |  |     * Optimize string adoption for equal or none dicts.  | 
9119  |  |     */  | 
9120  | 0  |     if ((sourceDoc != NULL) &&  | 
9121  | 0  |   (sourceDoc->dict == destDoc->dict))  | 
9122  | 0  |   adoptStr = 0;  | 
9123  | 0  |     else  | 
9124  | 0  |   adoptStr = 1;  | 
9125  |  |  | 
9126  |  |     /*  | 
9127  |  |     * Get the ns-map from the context if available.  | 
9128  |  |     */  | 
9129  | 0  |     if (ctxt)  | 
9130  | 0  |   nsMap = (xmlNsMapPtr) ctxt->namespaceMap;  | 
9131  |  |     /*  | 
9132  |  |     * Disable search for ns-decls in the parent-axis of the  | 
9133  |  |     * destination element, if:  | 
9134  |  |     * 1) there's no destination parent  | 
9135  |  |     * 2) custom ns-reference handling is used  | 
9136  |  |     */  | 
9137  | 0  |     if ((destParent == NULL) ||  | 
9138  | 0  |   (ctxt && ctxt->getNsForNodeFunc))  | 
9139  | 0  |     { | 
9140  | 0  |   parnsdone = 1;  | 
9141  | 0  |     } else  | 
9142  | 0  |   parnsdone = 0;  | 
9143  |  | 
  | 
9144  | 0  |     cur = node;  | 
9145  | 0  |     if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))  | 
9146  | 0  |   goto internal_error;  | 
9147  |  |  | 
9148  | 0  |     while (cur != NULL) { | 
9149  |  |   /*  | 
9150  |  |   * Paranoid source-doc sanity check.  | 
9151  |  |   */  | 
9152  | 0  |   if (cur->doc != sourceDoc) { | 
9153  |  |       /*  | 
9154  |  |       * We'll assume XIncluded nodes if the doc differs.  | 
9155  |  |       * TODO: Do we need to reconciliate XIncluded nodes?  | 
9156  |  |       * This here skips XIncluded nodes and tries to handle  | 
9157  |  |       * broken sequences.  | 
9158  |  |       */  | 
9159  | 0  |       if (cur->next == NULL)  | 
9160  | 0  |     goto leave_node;  | 
9161  | 0  |       do { | 
9162  | 0  |     cur = cur->next;  | 
9163  | 0  |     if ((cur->type == XML_XINCLUDE_END) ||  | 
9164  | 0  |         (cur->doc == node->doc))  | 
9165  | 0  |         break;  | 
9166  | 0  |       } while (cur->next != NULL);  | 
9167  |  |  | 
9168  | 0  |       if (cur->doc != node->doc)  | 
9169  | 0  |     goto leave_node;  | 
9170  | 0  |   }  | 
9171  | 0  |   cur->doc = destDoc;  | 
9172  | 0  |   switch (cur->type) { | 
9173  | 0  |       case XML_XINCLUDE_START:  | 
9174  | 0  |       case XML_XINCLUDE_END:  | 
9175  |  |     /*  | 
9176  |  |     * TODO  | 
9177  |  |     */  | 
9178  | 0  |     return (-1);  | 
9179  | 0  |       case XML_ELEMENT_NODE:  | 
9180  | 0  |     curElem = cur;  | 
9181  | 0  |     depth++;  | 
9182  |  |     /*  | 
9183  |  |     * Namespace declarations.  | 
9184  |  |     * - ns->href and ns->prefix are never in the dict, so  | 
9185  |  |     *   we need not move the values over to the destination dict.  | 
9186  |  |     * - Note that for custom handling of ns-references,  | 
9187  |  |     *   the ns-decls need not be stored in the ns-map,  | 
9188  |  |     *   since they won't be referenced by node->ns.  | 
9189  |  |     */  | 
9190  | 0  |     if ((cur->nsDef) &&  | 
9191  | 0  |         ((ctxt == NULL) || (ctxt->getNsForNodeFunc == NULL)))  | 
9192  | 0  |     { | 
9193  | 0  |         if (! parnsdone) { | 
9194  |  |       /*  | 
9195  |  |       * Gather @parent's in-scope ns-decls.  | 
9196  |  |       */  | 
9197  | 0  |       if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,  | 
9198  | 0  |           destParent) == -1)  | 
9199  | 0  |           goto internal_error;  | 
9200  | 0  |       parnsdone = 1;  | 
9201  | 0  |         }  | 
9202  | 0  |         for (ns = cur->nsDef; ns != NULL; ns = ns->next) { | 
9203  |  |       /*  | 
9204  |  |       * NOTE: ns->prefix and ns->href are never in the dict.  | 
9205  |  |       * XML_TREE_ADOPT_STR(ns->prefix)  | 
9206  |  |       * XML_TREE_ADOPT_STR(ns->href)  | 
9207  |  |       */  | 
9208  |  |       /*  | 
9209  |  |       * Does it shadow any ns-decl?  | 
9210  |  |       */  | 
9211  | 0  |       if (XML_NSMAP_NOTEMPTY(nsMap)) { | 
9212  | 0  |           XML_NSMAP_FOREACH(nsMap, mi) { | 
9213  | 0  |         if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&  | 
9214  | 0  |             (mi->shadowDepth == -1) &&  | 
9215  | 0  |             ((ns->prefix == mi->newNs->prefix) ||  | 
9216  | 0  |             xmlStrEqual(ns->prefix,  | 
9217  | 0  |             mi->newNs->prefix))) { | 
9218  |  | 
  | 
9219  | 0  |             mi->shadowDepth = depth;  | 
9220  | 0  |         }  | 
9221  | 0  |           }  | 
9222  | 0  |       }  | 
9223  |  |       /*  | 
9224  |  |       * Push mapping.  | 
9225  |  |       */  | 
9226  | 0  |       if (xmlDOMWrapNsMapAddItem(&nsMap, -1,  | 
9227  | 0  |           ns, ns, depth) == NULL)  | 
9228  | 0  |           goto internal_error;  | 
9229  | 0  |         }  | 
9230  | 0  |     }  | 
9231  |  |                 /* Falls through. */  | 
9232  | 0  |       case XML_ATTRIBUTE_NODE:  | 
9233  |  |     /* No namespace, no fun. */  | 
9234  | 0  |     if (cur->ns == NULL)  | 
9235  | 0  |         goto ns_end;  | 
9236  |  |  | 
9237  | 0  |     if (! parnsdone) { | 
9238  | 0  |         if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,  | 
9239  | 0  |       destParent) == -1)  | 
9240  | 0  |       goto internal_error;  | 
9241  | 0  |         parnsdone = 1;  | 
9242  | 0  |     }  | 
9243  |  |     /*  | 
9244  |  |     * Adopt ns-references.  | 
9245  |  |     */  | 
9246  | 0  |     if (XML_NSMAP_NOTEMPTY(nsMap)) { | 
9247  |  |         /*  | 
9248  |  |         * Search for a mapping.  | 
9249  |  |         */  | 
9250  | 0  |         XML_NSMAP_FOREACH(nsMap, mi) { | 
9251  | 0  |       if ((mi->shadowDepth == -1) &&  | 
9252  | 0  |           (cur->ns == mi->oldNs)) { | 
9253  |  | 
  | 
9254  | 0  |           cur->ns = mi->newNs;  | 
9255  | 0  |           goto ns_end;  | 
9256  | 0  |       }  | 
9257  | 0  |         }  | 
9258  | 0  |     }  | 
9259  |  |     /*  | 
9260  |  |     * No matching namespace in scope. We need a new one.  | 
9261  |  |     */  | 
9262  | 0  |     if ((ctxt) && (ctxt->getNsForNodeFunc)) { | 
9263  |  |         /*  | 
9264  |  |         * User-defined behaviour.  | 
9265  |  |         */  | 
9266  | 0  |         ns = ctxt->getNsForNodeFunc(ctxt, cur,  | 
9267  | 0  |       cur->ns->href, cur->ns->prefix);  | 
9268  |  |         /*  | 
9269  |  |         * Insert mapping if ns is available; it's the users fault  | 
9270  |  |         * if not.  | 
9271  |  |         */  | 
9272  | 0  |         if (xmlDOMWrapNsMapAddItem(&nsMap, -1,  | 
9273  | 0  |           cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)  | 
9274  | 0  |       goto internal_error;  | 
9275  | 0  |         cur->ns = ns;  | 
9276  | 0  |     } else { | 
9277  |  |         /*  | 
9278  |  |         * Acquire a normalized ns-decl and add it to the map.  | 
9279  |  |         */  | 
9280  | 0  |         if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc,  | 
9281  |  |       /* ns-decls on curElem or on destDoc->oldNs */  | 
9282  | 0  |       destParent ? curElem : NULL,  | 
9283  | 0  |       cur->ns, &ns,  | 
9284  | 0  |       &nsMap, depth,  | 
9285  | 0  |       ancestorsOnly,  | 
9286  |  |       /* ns-decls must be prefixed for attributes. */  | 
9287  | 0  |       (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)  | 
9288  | 0  |       goto internal_error;  | 
9289  | 0  |         cur->ns = ns;  | 
9290  | 0  |     }  | 
9291  | 0  | ns_end:  | 
9292  |  |     /*  | 
9293  |  |     * Further node properties.  | 
9294  |  |     * TODO: Is this all?  | 
9295  |  |     */  | 
9296  | 0  |     XML_TREE_ADOPT_STR(cur->name)  | 
9297  | 0  |     if (cur->type == XML_ELEMENT_NODE) { | 
9298  | 0  |         cur->psvi = NULL;  | 
9299  | 0  |         cur->line = 0;  | 
9300  | 0  |         cur->extra = 0;  | 
9301  |  |         /*  | 
9302  |  |         * Walk attributes.  | 
9303  |  |         */  | 
9304  | 0  |         if (cur->properties != NULL) { | 
9305  |  |       /*  | 
9306  |  |       * Process first attribute node.  | 
9307  |  |       */  | 
9308  | 0  |       cur = (xmlNodePtr) cur->properties;  | 
9309  | 0  |       continue;  | 
9310  | 0  |         }  | 
9311  | 0  |     } else { | 
9312  |  |         /*  | 
9313  |  |         * Attributes.  | 
9314  |  |         */  | 
9315  | 0  |         if ((sourceDoc != NULL) &&  | 
9316  | 0  |       (((xmlAttrPtr) cur)->atype == XML_ATTRIBUTE_ID))  | 
9317  | 0  |         { | 
9318  | 0  |       xmlRemoveID(sourceDoc, (xmlAttrPtr) cur);  | 
9319  | 0  |         }  | 
9320  | 0  |         ((xmlAttrPtr) cur)->atype = 0;  | 
9321  | 0  |         ((xmlAttrPtr) cur)->psvi = NULL;  | 
9322  | 0  |     }  | 
9323  | 0  |     break;  | 
9324  | 0  |       case XML_TEXT_NODE:  | 
9325  | 0  |       case XML_CDATA_SECTION_NODE:  | 
9326  |  |     /*  | 
9327  |  |     * This puts the content in the dest dict, only if  | 
9328  |  |     * it was previously in the source dict.  | 
9329  |  |     */  | 
9330  | 0  |     XML_TREE_ADOPT_STR_2(cur->content)  | 
9331  | 0  |     goto leave_node;  | 
9332  | 0  |       case XML_ENTITY_REF_NODE:  | 
9333  |  |     /*  | 
9334  |  |     * Remove reference to the entity-node.  | 
9335  |  |     */  | 
9336  | 0  |     cur->content = NULL;  | 
9337  | 0  |     cur->children = NULL;  | 
9338  | 0  |     cur->last = NULL;  | 
9339  | 0  |     if ((destDoc->intSubset) || (destDoc->extSubset)) { | 
9340  | 0  |         xmlEntityPtr ent;  | 
9341  |  |         /*  | 
9342  |  |         * Assign new entity-node if available.  | 
9343  |  |         */  | 
9344  | 0  |         ent = xmlGetDocEntity(destDoc, cur->name);  | 
9345  | 0  |         if (ent != NULL) { | 
9346  | 0  |       cur->content = ent->content;  | 
9347  | 0  |       cur->children = (xmlNodePtr) ent;  | 
9348  | 0  |       cur->last = (xmlNodePtr) ent;  | 
9349  | 0  |         }  | 
9350  | 0  |     }  | 
9351  | 0  |     goto leave_node;  | 
9352  | 0  |       case XML_PI_NODE:  | 
9353  | 0  |     XML_TREE_ADOPT_STR(cur->name)  | 
9354  | 0  |     XML_TREE_ADOPT_STR_2(cur->content)  | 
9355  | 0  |     break;  | 
9356  | 0  |       case XML_COMMENT_NODE:  | 
9357  | 0  |     break;  | 
9358  | 0  |       default:  | 
9359  | 0  |     goto internal_error;  | 
9360  | 0  |   }  | 
9361  |  |   /*  | 
9362  |  |   * Walk the tree.  | 
9363  |  |   */  | 
9364  | 0  |   if (cur->children != NULL) { | 
9365  | 0  |       cur = cur->children;  | 
9366  | 0  |       continue;  | 
9367  | 0  |   }  | 
9368  |  |  | 
9369  | 0  | leave_node:  | 
9370  | 0  |   if (cur == node)  | 
9371  | 0  |       break;  | 
9372  | 0  |   if ((cur->type == XML_ELEMENT_NODE) ||  | 
9373  | 0  |       (cur->type == XML_XINCLUDE_START) ||  | 
9374  | 0  |       (cur->type == XML_XINCLUDE_END))  | 
9375  | 0  |   { | 
9376  |  |       /*  | 
9377  |  |       * TODO: Do we expect nsDefs on XML_XINCLUDE_START?  | 
9378  |  |       */  | 
9379  | 0  |       if (XML_NSMAP_NOTEMPTY(nsMap)) { | 
9380  |  |     /*  | 
9381  |  |     * Pop mappings.  | 
9382  |  |     */  | 
9383  | 0  |     while ((nsMap->last != NULL) &&  | 
9384  | 0  |         (nsMap->last->depth >= depth))  | 
9385  | 0  |     { | 
9386  | 0  |         XML_NSMAP_POP(nsMap, mi)  | 
9387  | 0  |     }  | 
9388  |  |     /*  | 
9389  |  |     * Unshadow.  | 
9390  |  |     */  | 
9391  | 0  |     XML_NSMAP_FOREACH(nsMap, mi) { | 
9392  | 0  |         if (mi->shadowDepth >= depth)  | 
9393  | 0  |       mi->shadowDepth = -1;  | 
9394  | 0  |     }  | 
9395  | 0  |       }  | 
9396  | 0  |       depth--;  | 
9397  | 0  |   }  | 
9398  | 0  |   if (cur->next != NULL)  | 
9399  | 0  |       cur = cur->next;  | 
9400  | 0  |   else if ((cur->type == XML_ATTRIBUTE_NODE) &&  | 
9401  | 0  |       (cur->parent->children != NULL))  | 
9402  | 0  |   { | 
9403  | 0  |       cur = cur->parent->children;  | 
9404  | 0  |   } else { | 
9405  | 0  |       cur = cur->parent;  | 
9406  | 0  |       goto leave_node;  | 
9407  | 0  |   }  | 
9408  | 0  |     }  | 
9409  |  |  | 
9410  | 0  |     goto exit;  | 
9411  |  |  | 
9412  | 0  | internal_error:  | 
9413  | 0  |     ret = -1;  | 
9414  |  | 
  | 
9415  | 0  | exit:  | 
9416  |  |     /*  | 
9417  |  |     * Cleanup.  | 
9418  |  |     */  | 
9419  | 0  |     if (nsMap != NULL) { | 
9420  | 0  |   if ((ctxt) && (ctxt->namespaceMap == nsMap)) { | 
9421  |  |       /*  | 
9422  |  |       * Just cleanup the map but don't free.  | 
9423  |  |       */  | 
9424  | 0  |       if (nsMap->first) { | 
9425  | 0  |     if (nsMap->pool)  | 
9426  | 0  |         nsMap->last->next = nsMap->pool;  | 
9427  | 0  |     nsMap->pool = nsMap->first;  | 
9428  | 0  |     nsMap->first = NULL;  | 
9429  | 0  |       }  | 
9430  | 0  |   } else  | 
9431  | 0  |       xmlDOMWrapNsMapFree(nsMap);  | 
9432  | 0  |     }  | 
9433  | 0  |     return(ret);  | 
9434  | 0  | }  | 
9435  |  |  | 
9436  |  | /*  | 
9437  |  | * xmlDOMWrapCloneNode:  | 
9438  |  | * @ctxt: the optional context for custom processing  | 
9439  |  | * @sourceDoc: the optional sourceDoc  | 
9440  |  | * @node: the node to start with  | 
9441  |  | * @resNode: the clone of the given @node  | 
9442  |  | * @destDoc: the destination doc  | 
9443  |  | * @destParent: the optional new parent of @node in @destDoc  | 
9444  |  | * @deep: descend into child if set  | 
9445  |  | * @options: option flags  | 
9446  |  | *  | 
9447  |  | * References of out-of scope ns-decls are remapped to point to @destDoc:  | 
9448  |  | * 1) If @destParent is given, then nsDef entries on element-nodes are used  | 
9449  |  | * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used.  | 
9450  |  | *    This is the case when you don't know already where the cloned branch  | 
9451  |  | *    will be added to.  | 
9452  |  | *  | 
9453  |  | * If @destParent is given, it ensures that the tree is namespace  | 
9454  |  | * wellformed by creating additional ns-decls where needed.  | 
9455  |  | * Note that, since prefixes of already existent ns-decls can be  | 
9456  |  | * shadowed by this process, it could break QNames in attribute  | 
9457  |  | * values or element content.  | 
9458  |  | * TODO:  | 
9459  |  | *   1) What to do with XInclude? Currently this returns an error for XInclude.  | 
9460  |  | *  | 
9461  |  | * Returns 0 if the operation succeeded,  | 
9462  |  | *         1 if a node of unsupported (or not yet supported) type was given,  | 
9463  |  | *         -1 on API/internal errors.  | 
9464  |  | */  | 
9465  |  |  | 
9466  |  | int  | 
9467  |  | xmlDOMWrapCloneNode(xmlDOMWrapCtxtPtr ctxt,  | 
9468  |  |           xmlDocPtr sourceDoc,  | 
9469  |  |           xmlNodePtr node,  | 
9470  |  |           xmlNodePtr *resNode,  | 
9471  |  |           xmlDocPtr destDoc,  | 
9472  |  |           xmlNodePtr destParent,  | 
9473  |  |           int deep,  | 
9474  |  |           int options ATTRIBUTE_UNUSED)  | 
9475  | 0  | { | 
9476  | 0  |     int ret = 0;  | 
9477  | 0  |     xmlNodePtr cur, curElem = NULL;  | 
9478  | 0  |     xmlNsMapPtr nsMap = NULL;  | 
9479  | 0  |     xmlNsMapItemPtr mi;  | 
9480  | 0  |     xmlNsPtr ns;  | 
9481  | 0  |     int depth = -1;  | 
9482  |  |     /* int adoptStr = 1; */  | 
9483  |  |     /* gather @parent's ns-decls. */  | 
9484  | 0  |     int parnsdone = 0;  | 
9485  |  |     /*  | 
9486  |  |     * @ancestorsOnly:  | 
9487  |  |     * TODO: @ancestorsOnly should be set per option.  | 
9488  |  |     *  | 
9489  |  |     */  | 
9490  | 0  |     int ancestorsOnly = 0;  | 
9491  | 0  |     xmlNodePtr resultClone = NULL, clone = NULL, parentClone = NULL, prevClone = NULL;  | 
9492  | 0  |     xmlNsPtr cloneNs = NULL, *cloneNsDefSlot = NULL;  | 
9493  | 0  |     xmlDictPtr dict; /* The destination dict */  | 
9494  |  | 
  | 
9495  | 0  |     if ((node == NULL) || (resNode == NULL) || (destDoc == NULL))  | 
9496  | 0  |   return(-1);  | 
9497  |  |     /*  | 
9498  |  |     * TODO: Initially we support only element-nodes.  | 
9499  |  |     */  | 
9500  | 0  |     if (node->type != XML_ELEMENT_NODE)  | 
9501  | 0  |   return(1);  | 
9502  |  |     /*  | 
9503  |  |     * Check node->doc sanity.  | 
9504  |  |     */  | 
9505  | 0  |     if ((node->doc != NULL) && (sourceDoc != NULL) &&  | 
9506  | 0  |   (node->doc != sourceDoc)) { | 
9507  |  |   /*  | 
9508  |  |   * Might be an XIncluded node.  | 
9509  |  |   */  | 
9510  | 0  |   return (-1);  | 
9511  | 0  |     }  | 
9512  | 0  |     if (sourceDoc == NULL)  | 
9513  | 0  |   sourceDoc = node->doc;  | 
9514  | 0  |     if (sourceDoc == NULL)  | 
9515  | 0  |         return (-1);  | 
9516  |  |  | 
9517  | 0  |     dict = destDoc->dict;  | 
9518  |  |     /*  | 
9519  |  |     * Reuse the namespace map of the context.  | 
9520  |  |     */  | 
9521  | 0  |     if (ctxt)  | 
9522  | 0  |   nsMap = (xmlNsMapPtr) ctxt->namespaceMap;  | 
9523  |  | 
  | 
9524  | 0  |     *resNode = NULL;  | 
9525  |  | 
  | 
9526  | 0  |     cur = node;  | 
9527  | 0  |     if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))  | 
9528  | 0  |         return(-1);  | 
9529  |  |  | 
9530  | 0  |     while (cur != NULL) { | 
9531  | 0  |   if (cur->doc != sourceDoc) { | 
9532  |  |       /*  | 
9533  |  |       * We'll assume XIncluded nodes if the doc differs.  | 
9534  |  |       * TODO: Do we need to reconciliate XIncluded nodes?  | 
9535  |  |       * TODO: This here returns -1 in this case.  | 
9536  |  |       */  | 
9537  | 0  |       goto internal_error;  | 
9538  | 0  |   }  | 
9539  |  |   /*  | 
9540  |  |   * Create a new node.  | 
9541  |  |   */  | 
9542  | 0  |   switch (cur->type) { | 
9543  | 0  |       case XML_XINCLUDE_START:  | 
9544  | 0  |       case XML_XINCLUDE_END:  | 
9545  |  |     /*  | 
9546  |  |     * TODO: What to do with XInclude?  | 
9547  |  |     */  | 
9548  | 0  |     goto internal_error;  | 
9549  | 0  |     break;  | 
9550  | 0  |       case XML_ELEMENT_NODE:  | 
9551  | 0  |       case XML_TEXT_NODE:  | 
9552  | 0  |       case XML_CDATA_SECTION_NODE:  | 
9553  | 0  |       case XML_COMMENT_NODE:  | 
9554  | 0  |       case XML_PI_NODE:  | 
9555  | 0  |       case XML_DOCUMENT_FRAG_NODE:  | 
9556  | 0  |       case XML_ENTITY_REF_NODE:  | 
9557  | 0  |       case XML_ENTITY_NODE:  | 
9558  |  |     /*  | 
9559  |  |     * Nodes of xmlNode structure.  | 
9560  |  |     */  | 
9561  | 0  |     clone = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));  | 
9562  | 0  |     if (clone == NULL) { | 
9563  | 0  |         xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating a node"); | 
9564  | 0  |         goto internal_error;  | 
9565  | 0  |     }  | 
9566  | 0  |     memset(clone, 0, sizeof(xmlNode));  | 
9567  |  |     /*  | 
9568  |  |     * Set hierarchical links.  | 
9569  |  |     */  | 
9570  | 0  |     if (resultClone != NULL) { | 
9571  | 0  |         clone->parent = parentClone;  | 
9572  | 0  |         if (prevClone) { | 
9573  | 0  |       prevClone->next = clone;  | 
9574  | 0  |       clone->prev = prevClone;  | 
9575  | 0  |         } else  | 
9576  | 0  |       parentClone->children = clone;  | 
9577  | 0  |     } else  | 
9578  | 0  |         resultClone = clone;  | 
9579  |  | 
  | 
9580  | 0  |     break;  | 
9581  | 0  |       case XML_ATTRIBUTE_NODE:  | 
9582  |  |     /*  | 
9583  |  |     * Attributes (xmlAttr).  | 
9584  |  |     */  | 
9585  |  |                 /* Use xmlRealloc to avoid -Warray-bounds warning */  | 
9586  | 0  |     clone = (xmlNodePtr) xmlRealloc(NULL, sizeof(xmlAttr));  | 
9587  | 0  |     if (clone == NULL) { | 
9588  | 0  |         xmlTreeErrMemory("xmlDOMWrapCloneNode(): allocating an attr-node"); | 
9589  | 0  |         goto internal_error;  | 
9590  | 0  |     }  | 
9591  | 0  |     memset(clone, 0, sizeof(xmlAttr));  | 
9592  |  |     /*  | 
9593  |  |     * Set hierarchical links.  | 
9594  |  |     * TODO: Change this to add to the end of attributes.  | 
9595  |  |     */  | 
9596  | 0  |     if (resultClone != NULL) { | 
9597  | 0  |         clone->parent = parentClone;  | 
9598  | 0  |         if (prevClone) { | 
9599  | 0  |       prevClone->next = clone;  | 
9600  | 0  |       clone->prev = prevClone;  | 
9601  | 0  |         } else  | 
9602  | 0  |       parentClone->properties = (xmlAttrPtr) clone;  | 
9603  | 0  |     } else  | 
9604  | 0  |         resultClone = clone;  | 
9605  | 0  |     break;  | 
9606  | 0  |       default:  | 
9607  |  |     /*  | 
9608  |  |     * TODO QUESTION: Any other nodes expected?  | 
9609  |  |     */  | 
9610  | 0  |     goto internal_error;  | 
9611  | 0  |   }  | 
9612  |  |  | 
9613  | 0  |   clone->type = cur->type;  | 
9614  | 0  |   clone->doc = destDoc;  | 
9615  |  |  | 
9616  |  |   /*  | 
9617  |  |   * Clone the name of the node if any.  | 
9618  |  |   */  | 
9619  | 0  |   if (cur->name == xmlStringText)  | 
9620  | 0  |       clone->name = xmlStringText;  | 
9621  | 0  |   else if (cur->name == xmlStringTextNoenc)  | 
9622  |  |       /*  | 
9623  |  |       * NOTE: Although xmlStringTextNoenc is never assigned to a node  | 
9624  |  |       *   in tree.c, it might be set in Libxslt via  | 
9625  |  |       *   "xsl:disable-output-escaping".  | 
9626  |  |       */  | 
9627  | 0  |       clone->name = xmlStringTextNoenc;  | 
9628  | 0  |   else if (cur->name == xmlStringComment)  | 
9629  | 0  |       clone->name = xmlStringComment;  | 
9630  | 0  |   else if (cur->name != NULL) { | 
9631  | 0  |       DICT_CONST_COPY(cur->name, clone->name);  | 
9632  | 0  |   }  | 
9633  |  | 
  | 
9634  | 0  |   switch (cur->type) { | 
9635  | 0  |       case XML_XINCLUDE_START:  | 
9636  | 0  |       case XML_XINCLUDE_END:  | 
9637  |  |     /*  | 
9638  |  |     * TODO  | 
9639  |  |     */  | 
9640  | 0  |     return (-1);  | 
9641  | 0  |       case XML_ELEMENT_NODE:  | 
9642  | 0  |     curElem = cur;  | 
9643  | 0  |     depth++;  | 
9644  |  |     /*  | 
9645  |  |     * Namespace declarations.  | 
9646  |  |     */  | 
9647  | 0  |     if (cur->nsDef != NULL) { | 
9648  | 0  |         if (! parnsdone) { | 
9649  | 0  |       if (destParent && (ctxt == NULL)) { | 
9650  |  |           /*  | 
9651  |  |           * Gather @parent's in-scope ns-decls.  | 
9652  |  |           */  | 
9653  | 0  |           if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap,  | 
9654  | 0  |         destParent) == -1)  | 
9655  | 0  |         goto internal_error;  | 
9656  | 0  |       }  | 
9657  | 0  |       parnsdone = 1;  | 
9658  | 0  |         }  | 
9659  |  |         /*  | 
9660  |  |         * Clone namespace declarations.  | 
9661  |  |         */  | 
9662  | 0  |         cloneNsDefSlot = &(clone->nsDef);  | 
9663  | 0  |         for (ns = cur->nsDef; ns != NULL; ns = ns->next) { | 
9664  |  |       /*  | 
9665  |  |       * Create a new xmlNs.  | 
9666  |  |       */  | 
9667  | 0  |       cloneNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));  | 
9668  | 0  |       if (cloneNs == NULL) { | 
9669  | 0  |           xmlTreeErrMemory("xmlDOMWrapCloneNode(): " | 
9670  | 0  |         "allocating namespace");  | 
9671  | 0  |           return(-1);  | 
9672  | 0  |       }  | 
9673  | 0  |       memset(cloneNs, 0, sizeof(xmlNs));  | 
9674  | 0  |       cloneNs->type = XML_LOCAL_NAMESPACE;  | 
9675  |  | 
  | 
9676  | 0  |       if (ns->href != NULL)  | 
9677  | 0  |           cloneNs->href = xmlStrdup(ns->href);  | 
9678  | 0  |       if (ns->prefix != NULL)  | 
9679  | 0  |           cloneNs->prefix = xmlStrdup(ns->prefix);  | 
9680  |  | 
  | 
9681  | 0  |       *cloneNsDefSlot = cloneNs;  | 
9682  | 0  |       cloneNsDefSlot = &(cloneNs->next);  | 
9683  |  |  | 
9684  |  |       /*  | 
9685  |  |       * Note that for custom handling of ns-references,  | 
9686  |  |       * the ns-decls need not be stored in the ns-map,  | 
9687  |  |       * since they won't be referenced by node->ns.  | 
9688  |  |       */  | 
9689  | 0  |       if ((ctxt == NULL) ||  | 
9690  | 0  |           (ctxt->getNsForNodeFunc == NULL))  | 
9691  | 0  |       { | 
9692  |  |           /*  | 
9693  |  |           * Does it shadow any ns-decl?  | 
9694  |  |           */  | 
9695  | 0  |           if (XML_NSMAP_NOTEMPTY(nsMap)) { | 
9696  | 0  |         XML_NSMAP_FOREACH(nsMap, mi) { | 
9697  | 0  |             if ((mi->depth >= XML_TREE_NSMAP_PARENT) &&  | 
9698  | 0  |           (mi->shadowDepth == -1) &&  | 
9699  | 0  |           ((ns->prefix == mi->newNs->prefix) ||  | 
9700  | 0  |           xmlStrEqual(ns->prefix,  | 
9701  | 0  |           mi->newNs->prefix))) { | 
9702  |  |           /*  | 
9703  |  |           * Mark as shadowed at the current  | 
9704  |  |           * depth.  | 
9705  |  |           */  | 
9706  | 0  |           mi->shadowDepth = depth;  | 
9707  | 0  |             }  | 
9708  | 0  |         }  | 
9709  | 0  |           }  | 
9710  |  |           /*  | 
9711  |  |           * Push mapping.  | 
9712  |  |           */  | 
9713  | 0  |           if (xmlDOMWrapNsMapAddItem(&nsMap, -1,  | 
9714  | 0  |         ns, cloneNs, depth) == NULL)  | 
9715  | 0  |         goto internal_error;  | 
9716  | 0  |       }  | 
9717  | 0  |         }  | 
9718  | 0  |     }  | 
9719  |  |     /* cur->ns will be processed further down. */  | 
9720  | 0  |     break;  | 
9721  | 0  |       case XML_ATTRIBUTE_NODE:  | 
9722  |  |     /* IDs will be processed further down. */  | 
9723  |  |     /* cur->ns will be processed further down. */  | 
9724  | 0  |     break;  | 
9725  | 0  |       case XML_TEXT_NODE:  | 
9726  | 0  |       case XML_CDATA_SECTION_NODE:  | 
9727  |  |     /*  | 
9728  |  |     * Note that this will also cover the values of attributes.  | 
9729  |  |     */  | 
9730  | 0  |     DICT_COPY(cur->content, clone->content);  | 
9731  | 0  |     goto leave_node;  | 
9732  | 0  |       case XML_ENTITY_NODE:  | 
9733  |  |     /* TODO: What to do here? */  | 
9734  | 0  |     goto leave_node;  | 
9735  | 0  |       case XML_ENTITY_REF_NODE:  | 
9736  | 0  |     if (sourceDoc != destDoc) { | 
9737  | 0  |         if ((destDoc->intSubset) || (destDoc->extSubset)) { | 
9738  | 0  |       xmlEntityPtr ent;  | 
9739  |  |       /*  | 
9740  |  |       * Different doc: Assign new entity-node if available.  | 
9741  |  |       */  | 
9742  | 0  |       ent = xmlGetDocEntity(destDoc, cur->name);  | 
9743  | 0  |       if (ent != NULL) { | 
9744  | 0  |           clone->content = ent->content;  | 
9745  | 0  |           clone->children = (xmlNodePtr) ent;  | 
9746  | 0  |           clone->last = (xmlNodePtr) ent;  | 
9747  | 0  |       }  | 
9748  | 0  |         }  | 
9749  | 0  |     } else { | 
9750  |  |         /*  | 
9751  |  |         * Same doc: Use the current node's entity declaration  | 
9752  |  |         * and value.  | 
9753  |  |         */  | 
9754  | 0  |         clone->content = cur->content;  | 
9755  | 0  |         clone->children = cur->children;  | 
9756  | 0  |         clone->last = cur->last;  | 
9757  | 0  |     }  | 
9758  | 0  |     goto leave_node;  | 
9759  | 0  |       case XML_PI_NODE:  | 
9760  | 0  |     DICT_COPY(cur->content, clone->content);  | 
9761  | 0  |     goto leave_node;  | 
9762  | 0  |       case XML_COMMENT_NODE:  | 
9763  | 0  |     DICT_COPY(cur->content, clone->content);  | 
9764  | 0  |     goto leave_node;  | 
9765  | 0  |       default:  | 
9766  | 0  |     goto internal_error;  | 
9767  | 0  |   }  | 
9768  |  |  | 
9769  | 0  |   if (cur->ns == NULL)  | 
9770  | 0  |       goto end_ns_reference;  | 
9771  |  |  | 
9772  |  | /* handle_ns_reference: */  | 
9773  |  |   /*  | 
9774  |  |   ** The following will take care of references to ns-decls ********  | 
9775  |  |   ** and is intended only for element- and attribute-nodes.  | 
9776  |  |   **  | 
9777  |  |   */  | 
9778  | 0  |   if (! parnsdone) { | 
9779  | 0  |       if (destParent && (ctxt == NULL)) { | 
9780  | 0  |     if (xmlDOMWrapNSNormGatherInScopeNs(&nsMap, destParent) == -1)  | 
9781  | 0  |         goto internal_error;  | 
9782  | 0  |       }  | 
9783  | 0  |       parnsdone = 1;  | 
9784  | 0  |   }  | 
9785  |  |   /*  | 
9786  |  |   * Adopt ns-references.  | 
9787  |  |   */  | 
9788  | 0  |   if (XML_NSMAP_NOTEMPTY(nsMap)) { | 
9789  |  |       /*  | 
9790  |  |       * Search for a mapping.  | 
9791  |  |       */  | 
9792  | 0  |       XML_NSMAP_FOREACH(nsMap, mi) { | 
9793  | 0  |     if ((mi->shadowDepth == -1) &&  | 
9794  | 0  |         (cur->ns == mi->oldNs)) { | 
9795  |  |         /*  | 
9796  |  |         * This is the nice case: a mapping was found.  | 
9797  |  |         */  | 
9798  | 0  |         clone->ns = mi->newNs;  | 
9799  | 0  |         goto end_ns_reference;  | 
9800  | 0  |     }  | 
9801  | 0  |       }  | 
9802  | 0  |   }  | 
9803  |  |   /*  | 
9804  |  |   * No matching namespace in scope. We need a new one.  | 
9805  |  |   */  | 
9806  | 0  |   if ((ctxt != NULL) && (ctxt->getNsForNodeFunc != NULL)) { | 
9807  |  |       /*  | 
9808  |  |       * User-defined behaviour.  | 
9809  |  |       */  | 
9810  | 0  |       ns = ctxt->getNsForNodeFunc(ctxt, cur,  | 
9811  | 0  |     cur->ns->href, cur->ns->prefix);  | 
9812  |  |       /*  | 
9813  |  |       * Add user's mapping.  | 
9814  |  |       */  | 
9815  | 0  |       if (xmlDOMWrapNsMapAddItem(&nsMap, -1,  | 
9816  | 0  |     cur->ns, ns, XML_TREE_NSMAP_CUSTOM) == NULL)  | 
9817  | 0  |     goto internal_error;  | 
9818  | 0  |       clone->ns = ns;  | 
9819  | 0  |   } else { | 
9820  |  |       /*  | 
9821  |  |       * Acquire a normalized ns-decl and add it to the map.  | 
9822  |  |       */  | 
9823  | 0  |       if (xmlDOMWrapNSNormAcquireNormalizedNs(destDoc,  | 
9824  |  |     /* ns-decls on curElem or on destDoc->oldNs */  | 
9825  | 0  |     destParent ? curElem : NULL,  | 
9826  | 0  |     cur->ns, &ns,  | 
9827  | 0  |     &nsMap, depth,  | 
9828  |  |     /* if we need to search only in the ancestor-axis */  | 
9829  | 0  |     ancestorsOnly,  | 
9830  |  |     /* ns-decls must be prefixed for attributes. */  | 
9831  | 0  |     (cur->type == XML_ATTRIBUTE_NODE) ? 1 : 0) == -1)  | 
9832  | 0  |     goto internal_error;  | 
9833  | 0  |       clone->ns = ns;  | 
9834  | 0  |   }  | 
9835  |  |  | 
9836  | 0  | end_ns_reference:  | 
9837  |  |  | 
9838  |  |   /*  | 
9839  |  |   * Some post-processing.  | 
9840  |  |   *  | 
9841  |  |   * Handle ID attributes.  | 
9842  |  |   */  | 
9843  | 0  |   if ((clone->type == XML_ATTRIBUTE_NODE) &&  | 
9844  | 0  |       (clone->parent != NULL))  | 
9845  | 0  |   { | 
9846  | 0  |       if (xmlIsID(destDoc, clone->parent, (xmlAttrPtr) clone)) { | 
9847  |  | 
  | 
9848  | 0  |     xmlChar *idVal;  | 
9849  |  | 
  | 
9850  | 0  |     idVal = xmlNodeListGetString(cur->doc, cur->children, 1);  | 
9851  | 0  |     if (idVal != NULL) { | 
9852  | 0  |         if (xmlAddID(NULL, destDoc, idVal, (xmlAttrPtr) cur) == NULL) { | 
9853  |  |       /* TODO: error message. */  | 
9854  | 0  |       xmlFree(idVal);  | 
9855  | 0  |       goto internal_error;  | 
9856  | 0  |         }  | 
9857  | 0  |         xmlFree(idVal);  | 
9858  | 0  |     }  | 
9859  | 0  |       }  | 
9860  | 0  |   }  | 
9861  |  |   /*  | 
9862  |  |   **  | 
9863  |  |   ** The following will traverse the tree **************************  | 
9864  |  |   **  | 
9865  |  |   *  | 
9866  |  |   * Walk the element's attributes before descending into child-nodes.  | 
9867  |  |   */  | 
9868  | 0  |   if ((cur->type == XML_ELEMENT_NODE) && (cur->properties != NULL)) { | 
9869  | 0  |       prevClone = NULL;  | 
9870  | 0  |       parentClone = clone;  | 
9871  | 0  |       cur = (xmlNodePtr) cur->properties;  | 
9872  | 0  |       continue;  | 
9873  | 0  |   }  | 
9874  | 0  | into_content:  | 
9875  |  |   /*  | 
9876  |  |   * Descend into child-nodes.  | 
9877  |  |   */  | 
9878  | 0  |   if (cur->children != NULL) { | 
9879  | 0  |       if (deep || (cur->type == XML_ATTRIBUTE_NODE)) { | 
9880  | 0  |     prevClone = NULL;  | 
9881  | 0  |     parentClone = clone;  | 
9882  | 0  |     cur = cur->children;  | 
9883  | 0  |     continue;  | 
9884  | 0  |       }  | 
9885  | 0  |   }  | 
9886  |  |  | 
9887  | 0  | leave_node:  | 
9888  |  |   /*  | 
9889  |  |   * At this point we are done with the node, its content  | 
9890  |  |   * and an element-nodes's attribute-nodes.  | 
9891  |  |   */  | 
9892  | 0  |   if (cur == node)  | 
9893  | 0  |       break;  | 
9894  | 0  |   if ((cur->type == XML_ELEMENT_NODE) ||  | 
9895  | 0  |       (cur->type == XML_XINCLUDE_START) ||  | 
9896  | 0  |       (cur->type == XML_XINCLUDE_END)) { | 
9897  |  |       /*  | 
9898  |  |       * TODO: Do we expect nsDefs on XML_XINCLUDE_START?  | 
9899  |  |       */  | 
9900  | 0  |       if (XML_NSMAP_NOTEMPTY(nsMap)) { | 
9901  |  |     /*  | 
9902  |  |     * Pop mappings.  | 
9903  |  |     */  | 
9904  | 0  |     while ((nsMap->last != NULL) &&  | 
9905  | 0  |         (nsMap->last->depth >= depth))  | 
9906  | 0  |     { | 
9907  | 0  |         XML_NSMAP_POP(nsMap, mi)  | 
9908  | 0  |     }  | 
9909  |  |     /*  | 
9910  |  |     * Unshadow.  | 
9911  |  |     */  | 
9912  | 0  |     XML_NSMAP_FOREACH(nsMap, mi) { | 
9913  | 0  |         if (mi->shadowDepth >= depth)  | 
9914  | 0  |       mi->shadowDepth = -1;  | 
9915  | 0  |     }  | 
9916  | 0  |       }  | 
9917  | 0  |       depth--;  | 
9918  | 0  |   }  | 
9919  | 0  |   if (cur->next != NULL) { | 
9920  | 0  |       prevClone = clone;  | 
9921  | 0  |       cur = cur->next;  | 
9922  | 0  |   } else if (cur->type != XML_ATTRIBUTE_NODE) { | 
9923  |  |       /*  | 
9924  |  |       * Set clone->last.  | 
9925  |  |       */  | 
9926  | 0  |       if (clone->parent != NULL)  | 
9927  | 0  |     clone->parent->last = clone;  | 
9928  | 0  |       clone = clone->parent;  | 
9929  | 0  |       if (clone != NULL)  | 
9930  | 0  |     parentClone = clone->parent;  | 
9931  |  |       /*  | 
9932  |  |       * Process parent --> next;  | 
9933  |  |       */  | 
9934  | 0  |       cur = cur->parent;  | 
9935  | 0  |       goto leave_node;  | 
9936  | 0  |   } else { | 
9937  |  |       /* This is for attributes only. */  | 
9938  | 0  |       clone = clone->parent;  | 
9939  | 0  |       parentClone = clone->parent;  | 
9940  |  |       /*  | 
9941  |  |       * Process parent-element --> children.  | 
9942  |  |       */  | 
9943  | 0  |       cur = cur->parent;  | 
9944  | 0  |       goto into_content;  | 
9945  | 0  |   }  | 
9946  | 0  |     }  | 
9947  | 0  |     goto exit;  | 
9948  |  |  | 
9949  | 0  | internal_error:  | 
9950  | 0  |     ret = -1;  | 
9951  |  | 
  | 
9952  | 0  | exit:  | 
9953  |  |     /*  | 
9954  |  |     * Cleanup.  | 
9955  |  |     */  | 
9956  | 0  |     if (nsMap != NULL) { | 
9957  | 0  |   if ((ctxt) && (ctxt->namespaceMap == nsMap)) { | 
9958  |  |       /*  | 
9959  |  |       * Just cleanup the map but don't free.  | 
9960  |  |       */  | 
9961  | 0  |       if (nsMap->first) { | 
9962  | 0  |     if (nsMap->pool)  | 
9963  | 0  |         nsMap->last->next = nsMap->pool;  | 
9964  | 0  |     nsMap->pool = nsMap->first;  | 
9965  | 0  |     nsMap->first = NULL;  | 
9966  | 0  |       }  | 
9967  | 0  |   } else  | 
9968  | 0  |       xmlDOMWrapNsMapFree(nsMap);  | 
9969  | 0  |     }  | 
9970  |  |     /*  | 
9971  |  |     * TODO: Should we try a cleanup of the cloned node in case of a  | 
9972  |  |     * fatal error?  | 
9973  |  |     */  | 
9974  | 0  |     *resNode = resultClone;  | 
9975  | 0  |     return (ret);  | 
9976  | 0  | }  | 
9977  |  |  | 
9978  |  | /*  | 
9979  |  | * xmlDOMWrapAdoptAttr:  | 
9980  |  | * @ctxt: the optional context for custom processing  | 
9981  |  | * @sourceDoc: the optional source document of attr  | 
9982  |  | * @attr: the attribute-node to be adopted  | 
9983  |  | * @destDoc: the destination doc for adoption  | 
9984  |  | * @destParent: the optional new parent of @attr in @destDoc  | 
9985  |  | * @options: option flags  | 
9986  |  | *  | 
9987  |  | * @attr is adopted by @destDoc.  | 
9988  |  | * Ensures that ns-references point to @destDoc: either to  | 
9989  |  | * elements->nsDef entries if @destParent is given, or to  | 
9990  |  | * @destDoc->oldNs otherwise.  | 
9991  |  | *  | 
9992  |  | * Returns 0 if succeeded, -1 otherwise and on API/internal errors.  | 
9993  |  | */  | 
9994  |  | static int  | 
9995  |  | xmlDOMWrapAdoptAttr(xmlDOMWrapCtxtPtr ctxt,  | 
9996  |  |         xmlDocPtr sourceDoc,  | 
9997  |  |         xmlAttrPtr attr,  | 
9998  |  |         xmlDocPtr destDoc,  | 
9999  |  |         xmlNodePtr destParent,  | 
10000  |  |         int options ATTRIBUTE_UNUSED)  | 
10001  | 0  | { | 
10002  | 0  |     xmlNodePtr cur;  | 
10003  | 0  |     int adoptStr = 1;  | 
10004  |  | 
  | 
10005  | 0  |     if ((attr == NULL) || (destDoc == NULL))  | 
10006  | 0  |   return (-1);  | 
10007  |  |  | 
10008  | 0  |     attr->doc = destDoc;  | 
10009  | 0  |     if (attr->ns != NULL) { | 
10010  | 0  |   xmlNsPtr ns = NULL;  | 
10011  |  | 
  | 
10012  | 0  |   if (ctxt != NULL) { | 
10013  |  |       /* TODO: User defined. */  | 
10014  | 0  |   }  | 
10015  |  |   /* XML Namespace. */  | 
10016  | 0  |   if (IS_STR_XML(attr->ns->prefix)) { | 
10017  | 0  |       ns = xmlTreeEnsureXMLDecl(destDoc);  | 
10018  | 0  |   } else if (destParent == NULL) { | 
10019  |  |       /*  | 
10020  |  |       * Store in @destDoc->oldNs.  | 
10021  |  |       */  | 
10022  | 0  |       ns = xmlDOMWrapStoreNs(destDoc, attr->ns->href, attr->ns->prefix);  | 
10023  | 0  |   } else { | 
10024  |  |       /*  | 
10025  |  |       * Declare on @destParent.  | 
10026  |  |       */  | 
10027  | 0  |       if (xmlSearchNsByNamespaceStrict(destDoc, destParent, attr->ns->href,  | 
10028  | 0  |     &ns, 1) == -1)  | 
10029  | 0  |     goto internal_error;  | 
10030  | 0  |       if (ns == NULL) { | 
10031  | 0  |     ns = xmlDOMWrapNSNormDeclareNsForced(destDoc, destParent,  | 
10032  | 0  |         attr->ns->href, attr->ns->prefix, 1);  | 
10033  | 0  |       }  | 
10034  | 0  |   }  | 
10035  | 0  |   if (ns == NULL)  | 
10036  | 0  |       goto internal_error;  | 
10037  | 0  |   attr->ns = ns;  | 
10038  | 0  |     }  | 
10039  |  |  | 
10040  | 0  |     XML_TREE_ADOPT_STR(attr->name);  | 
10041  | 0  |     attr->atype = 0;  | 
10042  | 0  |     attr->psvi = NULL;  | 
10043  |  |     /*  | 
10044  |  |     * Walk content.  | 
10045  |  |     */  | 
10046  | 0  |     if (attr->children == NULL)  | 
10047  | 0  |   return (0);  | 
10048  | 0  |     cur = attr->children;  | 
10049  | 0  |     if ((cur != NULL) && (cur->type == XML_NAMESPACE_DECL))  | 
10050  | 0  |         goto internal_error;  | 
10051  | 0  |     while (cur != NULL) { | 
10052  | 0  |   cur->doc = destDoc;  | 
10053  | 0  |   switch (cur->type) { | 
10054  | 0  |       case XML_TEXT_NODE:  | 
10055  | 0  |       case XML_CDATA_SECTION_NODE:  | 
10056  | 0  |     XML_TREE_ADOPT_STR_2(cur->content)  | 
10057  | 0  |     break;  | 
10058  | 0  |       case XML_ENTITY_REF_NODE:  | 
10059  |  |     /*  | 
10060  |  |     * Remove reference to the entity-node.  | 
10061  |  |     */  | 
10062  | 0  |     cur->content = NULL;  | 
10063  | 0  |     cur->children = NULL;  | 
10064  | 0  |     cur->last = NULL;  | 
10065  | 0  |     if ((destDoc->intSubset) || (destDoc->extSubset)) { | 
10066  | 0  |         xmlEntityPtr ent;  | 
10067  |  |         /*  | 
10068  |  |         * Assign new entity-node if available.  | 
10069  |  |         */  | 
10070  | 0  |         ent = xmlGetDocEntity(destDoc, cur->name);  | 
10071  | 0  |         if (ent != NULL) { | 
10072  | 0  |       cur->content = ent->content;  | 
10073  | 0  |       cur->children = (xmlNodePtr) ent;  | 
10074  | 0  |       cur->last = (xmlNodePtr) ent;  | 
10075  | 0  |         }  | 
10076  | 0  |     }  | 
10077  | 0  |     break;  | 
10078  | 0  |       default:  | 
10079  | 0  |     break;  | 
10080  | 0  |   }  | 
10081  | 0  |   if (cur->children != NULL) { | 
10082  | 0  |       cur = cur->children;  | 
10083  | 0  |       continue;  | 
10084  | 0  |   }  | 
10085  | 0  | next_sibling:  | 
10086  | 0  |   if (cur == (xmlNodePtr) attr)  | 
10087  | 0  |       break;  | 
10088  | 0  |   if (cur->next != NULL)  | 
10089  | 0  |       cur = cur->next;  | 
10090  | 0  |   else { | 
10091  | 0  |       cur = cur->parent;  | 
10092  | 0  |       goto next_sibling;  | 
10093  | 0  |   }  | 
10094  | 0  |     }  | 
10095  | 0  |     return (0);  | 
10096  | 0  | internal_error:  | 
10097  | 0  |     return (-1);  | 
10098  | 0  | }  | 
10099  |  |  | 
10100  |  | /*  | 
10101  |  | * xmlDOMWrapAdoptNode:  | 
10102  |  | * @ctxt: the optional context for custom processing  | 
10103  |  | * @sourceDoc: the optional sourceDoc  | 
10104  |  | * @node: the node to start with  | 
10105  |  | * @destDoc: the destination doc  | 
10106  |  | * @destParent: the optional new parent of @node in @destDoc  | 
10107  |  | * @options: option flags  | 
10108  |  | *  | 
10109  |  | * References of out-of scope ns-decls are remapped to point to @destDoc:  | 
10110  |  | * 1) If @destParent is given, then nsDef entries on element-nodes are used  | 
10111  |  | * 2) If *no* @destParent is given, then @destDoc->oldNs entries are used  | 
10112  |  | *    This is the case when you have an unlinked node and just want to move it  | 
10113  |  | *    to the context of  | 
10114  |  | *  | 
10115  |  | * If @destParent is given, it ensures that the tree is namespace  | 
10116  |  | * wellformed by creating additional ns-decls where needed.  | 
10117  |  | * Note that, since prefixes of already existent ns-decls can be  | 
10118  |  | * shadowed by this process, it could break QNames in attribute  | 
10119  |  | * values or element content.  | 
10120  |  | * NOTE: This function was not intensively tested.  | 
10121  |  | *  | 
10122  |  | * Returns 0 if the operation succeeded,  | 
10123  |  | *         1 if a node of unsupported type was given,  | 
10124  |  | *         2 if a node of not yet supported type was given and  | 
10125  |  | *         -1 on API/internal errors.  | 
10126  |  | */  | 
10127  |  | int  | 
10128  |  | xmlDOMWrapAdoptNode(xmlDOMWrapCtxtPtr ctxt,  | 
10129  |  |         xmlDocPtr sourceDoc,  | 
10130  |  |         xmlNodePtr node,  | 
10131  |  |         xmlDocPtr destDoc,  | 
10132  |  |         xmlNodePtr destParent,  | 
10133  |  |         int options)  | 
10134  | 0  | { | 
10135  | 0  |     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL) ||  | 
10136  | 0  |         (destDoc == NULL) ||  | 
10137  | 0  |   ((destParent != NULL) && (destParent->doc != destDoc)))  | 
10138  | 0  |   return(-1);  | 
10139  |  |     /*  | 
10140  |  |     * Check node->doc sanity.  | 
10141  |  |     */  | 
10142  | 0  |     if ((node->doc != NULL) && (sourceDoc != NULL) &&  | 
10143  | 0  |   (node->doc != sourceDoc)) { | 
10144  |  |   /*  | 
10145  |  |   * Might be an XIncluded node.  | 
10146  |  |   */  | 
10147  | 0  |   return (-1);  | 
10148  | 0  |     }  | 
10149  | 0  |     if (sourceDoc == NULL)  | 
10150  | 0  |   sourceDoc = node->doc;  | 
10151  | 0  |     if (sourceDoc == destDoc)  | 
10152  | 0  |   return (-1);  | 
10153  | 0  |     switch (node->type) { | 
10154  | 0  |   case XML_ELEMENT_NODE:  | 
10155  | 0  |   case XML_ATTRIBUTE_NODE:  | 
10156  | 0  |   case XML_TEXT_NODE:  | 
10157  | 0  |   case XML_CDATA_SECTION_NODE:  | 
10158  | 0  |   case XML_ENTITY_REF_NODE:  | 
10159  | 0  |   case XML_PI_NODE:  | 
10160  | 0  |   case XML_COMMENT_NODE:  | 
10161  | 0  |       break;  | 
10162  | 0  |   case XML_DOCUMENT_FRAG_NODE:  | 
10163  |  |       /* TODO: Support document-fragment-nodes. */  | 
10164  | 0  |       return (2);  | 
10165  | 0  |   default:  | 
10166  | 0  |       return (1);  | 
10167  | 0  |     }  | 
10168  |  |     /*  | 
10169  |  |     * Unlink only if @node was not already added to @destParent.  | 
10170  |  |     */  | 
10171  | 0  |     if ((node->parent != NULL) && (destParent != node->parent))  | 
10172  | 0  |   xmlUnlinkNode(node);  | 
10173  |  | 
  | 
10174  | 0  |     if (node->type == XML_ELEMENT_NODE) { | 
10175  | 0  |       return (xmlDOMWrapAdoptBranch(ctxt, sourceDoc, node,  | 
10176  | 0  |         destDoc, destParent, options));  | 
10177  | 0  |     } else if (node->type == XML_ATTRIBUTE_NODE) { | 
10178  | 0  |       return (xmlDOMWrapAdoptAttr(ctxt, sourceDoc,  | 
10179  | 0  |     (xmlAttrPtr) node, destDoc, destParent, options));  | 
10180  | 0  |     } else { | 
10181  | 0  |   xmlNodePtr cur = node;  | 
10182  | 0  |   int adoptStr = 1;  | 
10183  |  | 
  | 
10184  | 0  |   cur->doc = destDoc;  | 
10185  |  |   /*  | 
10186  |  |   * Optimize string adoption.  | 
10187  |  |   */  | 
10188  | 0  |   if ((sourceDoc != NULL) &&  | 
10189  | 0  |       (sourceDoc->dict == destDoc->dict))  | 
10190  | 0  |     adoptStr = 0;  | 
10191  | 0  |   switch (node->type) { | 
10192  | 0  |       case XML_TEXT_NODE:  | 
10193  | 0  |       case XML_CDATA_SECTION_NODE:  | 
10194  | 0  |     XML_TREE_ADOPT_STR_2(node->content)  | 
10195  | 0  |         break;  | 
10196  | 0  |       case XML_ENTITY_REF_NODE:  | 
10197  |  |     /*  | 
10198  |  |     * Remove reference to the entity-node.  | 
10199  |  |     */  | 
10200  | 0  |     node->content = NULL;  | 
10201  | 0  |     node->children = NULL;  | 
10202  | 0  |     node->last = NULL;  | 
10203  | 0  |     if ((destDoc->intSubset) || (destDoc->extSubset)) { | 
10204  | 0  |         xmlEntityPtr ent;  | 
10205  |  |         /*  | 
10206  |  |         * Assign new entity-node if available.  | 
10207  |  |         */  | 
10208  | 0  |         ent = xmlGetDocEntity(destDoc, node->name);  | 
10209  | 0  |         if (ent != NULL) { | 
10210  | 0  |       node->content = ent->content;  | 
10211  | 0  |       node->children = (xmlNodePtr) ent;  | 
10212  | 0  |       node->last = (xmlNodePtr) ent;  | 
10213  | 0  |         }  | 
10214  | 0  |     }  | 
10215  | 0  |     XML_TREE_ADOPT_STR(node->name)  | 
10216  | 0  |     break;  | 
10217  | 0  |       case XML_PI_NODE: { | 
10218  | 0  |     XML_TREE_ADOPT_STR(node->name)  | 
10219  | 0  |     XML_TREE_ADOPT_STR_2(node->content)  | 
10220  | 0  |     break;  | 
10221  | 0  |       }  | 
10222  | 0  |       default:  | 
10223  | 0  |     break;  | 
10224  | 0  |   }  | 
10225  | 0  |     }  | 
10226  | 0  |     return (0);  | 
10227  | 0  | }  | 
10228  |  |  | 
10229  |  | /************************************************************************  | 
10230  |  |  *                  *  | 
10231  |  |  *      XHTML detection         *  | 
10232  |  |  *                  *  | 
10233  |  |  ************************************************************************/  | 
10234  |  |  | 
10235  | 0  | #define XHTML_STRICT_PUBLIC_ID BAD_CAST \  | 
10236  | 0  |    "-//W3C//DTD XHTML 1.0 Strict//EN"  | 
10237  | 0  | #define XHTML_STRICT_SYSTEM_ID BAD_CAST \  | 
10238  | 0  |    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"  | 
10239  | 0  | #define XHTML_FRAME_PUBLIC_ID BAD_CAST \  | 
10240  | 0  |    "-//W3C//DTD XHTML 1.0 Frameset//EN"  | 
10241  | 0  | #define XHTML_FRAME_SYSTEM_ID BAD_CAST \  | 
10242  | 0  |    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"  | 
10243  | 0  | #define XHTML_TRANS_PUBLIC_ID BAD_CAST \  | 
10244  | 0  |    "-//W3C//DTD XHTML 1.0 Transitional//EN"  | 
10245  | 0  | #define XHTML_TRANS_SYSTEM_ID BAD_CAST \  | 
10246  | 0  |    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"  | 
10247  |  |  | 
10248  |  | /**  | 
10249  |  |  * xmlIsXHTML:  | 
10250  |  |  * @systemID:  the system identifier  | 
10251  |  |  * @publicID:  the public identifier  | 
10252  |  |  *  | 
10253  |  |  * Try to find if the document correspond to an XHTML DTD  | 
10254  |  |  *  | 
10255  |  |  * Returns 1 if true, 0 if not and -1 in case of error  | 
10256  |  |  */  | 
10257  |  | int  | 
10258  | 0  | xmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID) { | 
10259  | 0  |     if ((systemID == NULL) && (publicID == NULL))  | 
10260  | 0  |   return(-1);  | 
10261  | 0  |     if (publicID != NULL) { | 
10262  | 0  |   if (xmlStrEqual(publicID, XHTML_STRICT_PUBLIC_ID)) return(1);  | 
10263  | 0  |   if (xmlStrEqual(publicID, XHTML_FRAME_PUBLIC_ID)) return(1);  | 
10264  | 0  |   if (xmlStrEqual(publicID, XHTML_TRANS_PUBLIC_ID)) return(1);  | 
10265  | 0  |     }  | 
10266  | 0  |     if (systemID != NULL) { | 
10267  | 0  |   if (xmlStrEqual(systemID, XHTML_STRICT_SYSTEM_ID)) return(1);  | 
10268  | 0  |   if (xmlStrEqual(systemID, XHTML_FRAME_SYSTEM_ID)) return(1);  | 
10269  | 0  |   if (xmlStrEqual(systemID, XHTML_TRANS_SYSTEM_ID)) return(1);  | 
10270  | 0  |     }  | 
10271  | 0  |     return(0);  | 
10272  | 0  | }  | 
10273  |  |  |