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