Annotation of XML/tree.c, revision 1.133
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.
1.120 veillard 132: * We use href==NULL in the case of an element creation where the namespace
133: * was not defined.
1.83 daniel 134: * Returns returns a new namespace pointer or NULL
1.1 veillard 135: */
1.28 daniel 136: xmlNsPtr
1.61 daniel 137: xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) {
1.16 daniel 138: xmlNsPtr cur;
1.1 veillard 139:
140: /*
1.90 daniel 141: * Allocate a new Namespace and fill the fields.
1.1 veillard 142: */
1.57 daniel 143: cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
1.1 veillard 144: if (cur == NULL) {
1.16 daniel 145: fprintf(stderr, "xmlNewNs : malloc failed\n");
1.1 veillard 146: return(NULL);
147: }
1.90 daniel 148: memset(cur, 0, sizeof(xmlNs));
149: cur->type = XML_LOCAL_NAMESPACE;
1.1 veillard 150:
1.19 daniel 151: if (href != NULL)
152: cur->href = xmlStrdup(href);
153: if (prefix != NULL)
154: cur->prefix = xmlStrdup(prefix);
155:
156: /*
157: * Add it at the end to preserve parsing order ...
1.83 daniel 158: * and checks for existing use of the prefix
1.19 daniel 159: */
160: if (node != NULL) {
161: if (node->nsDef == NULL) {
162: node->nsDef = cur;
163: } else {
164: xmlNsPtr prev = node->nsDef;
165:
1.86 daniel 166: if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
1.128 veillard 167: (xmlStrEqual(prev->prefix, cur->prefix))) {
1.86 daniel 168: xmlFreeNs(cur);
169: return(NULL);
170: }
1.83 daniel 171: while (prev->next != NULL) {
1.86 daniel 172: prev = prev->next;
1.83 daniel 173: if (((prev->prefix == NULL) && (cur->prefix == NULL)) ||
1.128 veillard 174: (xmlStrEqual(prev->prefix, cur->prefix))) {
1.83 daniel 175: xmlFreeNs(cur);
176: return(NULL);
177: }
178: }
1.19 daniel 179: prev->next = cur;
180: }
181: }
182: return(cur);
183: }
184:
1.23 daniel 185: /**
186: * xmlNewGlobalNs:
187: * @doc: the document carrying the namespace
188: * @href: the URI associated
189: * @prefix: the prefix for the namespace
190: *
1.83 daniel 191: * Creation of a Namespace, the old way using PI and without scoping
192: * DEPRECATED !!!
1.85 daniel 193: * It now create a namespace on the root element of the document if found.
1.83 daniel 194: * Returns NULL this functionnality had been removed
1.19 daniel 195: */
1.28 daniel 196: xmlNsPtr
1.61 daniel 197: xmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) {
1.85 daniel 198: xmlNodePtr root;
199:
1.86 daniel 200: xmlNsPtr cur;
201:
1.85 daniel 202: root = xmlDocGetRootElement(doc);
203: if (root != NULL)
204: return(xmlNewNs(root, href, prefix));
1.86 daniel 205:
206: /*
207: * if there is no root element yet, create an old Namespace type
208: * and it will be moved to the root at save time.
209: */
210: cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
211: if (cur == NULL) {
212: fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
213: return(NULL);
214: }
1.90 daniel 215: memset(cur, 0, sizeof(xmlNs));
216: cur->type = XML_GLOBAL_NAMESPACE;
1.86 daniel 217:
218: if (href != NULL)
219: cur->href = xmlStrdup(href);
220: if (prefix != NULL)
221: cur->prefix = xmlStrdup(prefix);
222:
223: /*
224: * Add it at the end to preserve parsing order ...
225: */
226: if (doc != NULL) {
227: if (doc->oldNs == NULL) {
228: doc->oldNs = cur;
229: } else {
230: xmlNsPtr prev = doc->oldNs;
231:
232: while (prev->next != NULL) prev = prev->next;
233: prev->next = cur;
234: }
235: }
236:
237: return(NULL);
1.1 veillard 238: }
239:
1.23 daniel 240: /**
241: * xmlSetNs:
242: * @node: a node in the document
243: * @ns: a namespace pointer
244: *
245: * Associate a namespace to a node, a posteriori.
1.19 daniel 246: */
1.28 daniel 247: void
248: xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
1.19 daniel 249: if (node == NULL) {
1.86 daniel 250: #ifdef DEBUG_TREE
1.19 daniel 251: fprintf(stderr, "xmlSetNs: node == NULL\n");
1.94 daniel 252: #endif
1.19 daniel 253: return;
254: }
255: node->ns = ns;
256: }
257:
1.23 daniel 258: /**
259: * xmlFreeNs:
260: * @cur: the namespace pointer
261: *
262: * Free up the structures associated to a namespace
1.1 veillard 263: */
1.28 daniel 264: void
265: xmlFreeNs(xmlNsPtr cur) {
1.1 veillard 266: if (cur == NULL) {
1.86 daniel 267: #ifdef DEBUG_TREE
1.17 daniel 268: fprintf(stderr, "xmlFreeNs : ns == NULL\n");
1.86 daniel 269: #endif
1.1 veillard 270: return;
271: }
1.57 daniel 272: if (cur->href != NULL) xmlFree((char *) cur->href);
273: if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
1.16 daniel 274: memset(cur, -1, sizeof(xmlNs));
1.57 daniel 275: xmlFree(cur);
1.1 veillard 276: }
277:
1.23 daniel 278: /**
279: * xmlFreeNsList:
280: * @cur: the first namespace pointer
281: *
282: * Free up all the structures associated to the chained namespaces.
1.6 veillard 283: */
1.28 daniel 284: void
285: xmlFreeNsList(xmlNsPtr cur) {
1.16 daniel 286: xmlNsPtr next;
1.6 veillard 287: if (cur == NULL) {
1.86 daniel 288: #ifdef DEBUG_TREE
1.16 daniel 289: fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
1.86 daniel 290: #endif
1.6 veillard 291: return;
292: }
293: while (cur != NULL) {
294: next = cur->next;
1.16 daniel 295: xmlFreeNs(cur);
1.6 veillard 296: cur = next;
297: }
298: }
299:
1.23 daniel 300: /**
301: * xmlNewDtd:
302: * @doc: the document pointer
303: * @name: the DTD name
304: * @ExternalID: the external ID
305: * @SystemID: the system ID
306: *
1.94 daniel 307: * Creation of a new DTD for the external subset. To create an
308: * internal subset, use xmlCreateIntSubset().
309: *
1.36 daniel 310: * Returns a pointer to the new DTD structure
1.17 daniel 311: */
1.28 daniel 312: xmlDtdPtr
1.61 daniel 313: xmlNewDtd(xmlDocPtr doc, const xmlChar *name,
314: const xmlChar *ExternalID, const xmlChar *SystemID) {
1.17 daniel 315: xmlDtdPtr cur;
316:
1.31 daniel 317: if ((doc != NULL) && (doc->extSubset != NULL)) {
1.86 daniel 318: #ifdef DEBUG_TREE
1.17 daniel 319: fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
1.31 daniel 320: /* !!! */ (char *) name, doc->name,
321: /* !!! */ (char *)doc->extSubset->name);
1.86 daniel 322: #endif
323: return(NULL);
1.17 daniel 324: }
325:
326: /*
327: * Allocate a new DTD and fill the fields.
328: */
1.57 daniel 329: cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
1.17 daniel 330: if (cur == NULL) {
1.31 daniel 331: fprintf(stderr, "xmlNewDtd : malloc failed\n");
332: return(NULL);
333: }
1.90 daniel 334: memset(cur, 0 , sizeof(xmlDtd));
335: cur->type = XML_DTD_NODE;
1.31 daniel 336:
337: if (name != NULL)
338: cur->name = xmlStrdup(name);
339: if (ExternalID != NULL)
340: cur->ExternalID = xmlStrdup(ExternalID);
341: if (SystemID != NULL)
342: cur->SystemID = xmlStrdup(SystemID);
343: if (doc != NULL)
344: doc->extSubset = cur;
1.94 daniel 345: cur->doc = doc;
1.31 daniel 346:
347: return(cur);
348: }
349:
350: /**
1.92 daniel 351: * xmlGetIntSubset:
352: * @doc: the document pointer
353: *
354: * Get the internal subset of a document
355: * Returns a pointer to the DTD structure or NULL if not found
356: */
357:
358: xmlDtdPtr
359: xmlGetIntSubset(xmlDocPtr doc) {
360: xmlNodePtr cur;
361:
362: if (doc == NULL)
363: return(NULL);
364: cur = doc->children;
365: while (cur != NULL) {
366: if (cur->type == XML_DTD_NODE)
367: return((xmlDtdPtr) cur);
368: cur = cur->next;
369: }
370: return((xmlDtdPtr) doc->intSubset);
371: }
372:
373: /**
1.31 daniel 374: * xmlCreateIntSubset:
375: * @doc: the document pointer
376: * @name: the DTD name
377: * @ExternalID: the external ID
378: * @SystemID: the system ID
379: *
1.36 daniel 380: * Create the internal subset of a document
381: * Returns a pointer to the new DTD structure
1.31 daniel 382: */
383: xmlDtdPtr
1.61 daniel 384: xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
385: const xmlChar *ExternalID, const xmlChar *SystemID) {
1.31 daniel 386: xmlDtdPtr cur;
387:
1.92 daniel 388: if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) {
1.86 daniel 389: #ifdef DEBUG_TREE
1.31 daniel 390: fprintf(stderr,
391: "xmlCreateIntSubset(): document %s already have an internal subset\n",
392: doc->name);
1.86 daniel 393: #endif
1.31 daniel 394: return(NULL);
395: }
396:
397: /*
398: * Allocate a new DTD and fill the fields.
399: */
1.57 daniel 400: cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
1.31 daniel 401: if (cur == NULL) {
402: fprintf(stderr, "xmlNewDtd : malloc failed\n");
1.17 daniel 403: return(NULL);
404: }
1.90 daniel 405: memset(cur, 0, sizeof(xmlDtd));
406: cur->type = XML_DTD_NODE;
1.17 daniel 407:
408: if (name != NULL)
409: cur->name = xmlStrdup(name);
410: if (ExternalID != NULL)
411: cur->ExternalID = xmlStrdup(ExternalID);
412: if (SystemID != NULL)
413: cur->SystemID = xmlStrdup(SystemID);
1.90 daniel 414: if (doc != NULL) {
1.31 daniel 415: doc->intSubset = cur;
1.90 daniel 416: cur->parent = doc;
1.94 daniel 417: cur->doc = doc;
1.92 daniel 418: if (doc->children == NULL) {
419: doc->children = (xmlNodePtr) cur;
420: doc->last = (xmlNodePtr) cur;
421: } else {
422: xmlNodePtr prev;
423:
1.119 veillard 424: if (doc->type == XML_HTML_DOCUMENT_NODE) {
425: prev = doc->children;
426: prev->prev = (xmlNodePtr) cur;
427: cur->next = prev;
428: doc->children = (xmlNodePtr) cur;
429: } else {
430: prev = doc->last;
431: prev->next = (xmlNodePtr) cur;
432: cur->prev = prev;
433: doc->last = (xmlNodePtr) cur;
434: }
1.92 daniel 435: }
1.90 daniel 436: }
1.17 daniel 437: return(cur);
438: }
439:
1.23 daniel 440: /**
441: * xmlFreeDtd:
442: * @cur: the DTD structure to free up
443: *
444: * Free a DTD structure.
1.17 daniel 445: */
1.28 daniel 446: void
447: xmlFreeDtd(xmlDtdPtr cur) {
1.17 daniel 448: if (cur == NULL) {
1.86 daniel 449: #ifdef DEBUG_TREE
1.17 daniel 450: fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
1.86 daniel 451: #endif
1.17 daniel 452: return;
453: }
1.97 daniel 454: if (cur->children != NULL) {
455: xmlNodePtr next, c = cur->children;
456:
457: /*
458: * Cleanup all the DTD comments they are not in the Dtd
459: * indexes.
460: */
461: while (c != NULL) {
462: next = c->next;
463: if (c->type == XML_COMMENT_NODE) {
464: xmlUnlinkNode(c);
465: xmlFreeNode(c);
466: }
467: c = next;
468: }
469: }
1.57 daniel 470: if (cur->name != NULL) xmlFree((char *) cur->name);
471: if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
472: if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
1.97 daniel 473: /* TODO !!! */
1.35 daniel 474: if (cur->notations != NULL)
475: xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
1.97 daniel 476:
1.17 daniel 477: if (cur->elements != NULL)
1.33 daniel 478: xmlFreeElementTable((xmlElementTablePtr) cur->elements);
1.34 daniel 479: if (cur->attributes != NULL)
480: xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
1.17 daniel 481: if (cur->entities != NULL)
482: xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
1.132 veillard 483: if (cur->pentities != NULL)
484: xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->pentities);
1.97 daniel 485:
1.17 daniel 486: memset(cur, -1, sizeof(xmlDtd));
1.57 daniel 487: xmlFree(cur);
1.17 daniel 488: }
489:
1.23 daniel 490: /**
491: * xmlNewDoc:
1.61 daniel 492: * @version: xmlChar string giving the version of XML "1.0"
1.23 daniel 493: *
1.36 daniel 494: * Returns a new document
1.1 veillard 495: */
1.28 daniel 496: xmlDocPtr
1.61 daniel 497: xmlNewDoc(const xmlChar *version) {
1.1 veillard 498: xmlDocPtr cur;
499:
1.130 veillard 500: if (version == NULL)
501: version = (const xmlChar *) "1.0";
1.1 veillard 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) {
1.118 veillard 796: if ((node->type == XML_TEXT_NODE) ||
797: (node->type == XML_CDATA_SECTION_NODE)) {
1.84 daniel 798: if (inLine) {
1.70 daniel 799: #ifndef XML_USE_BUFFER_CONTENT
1.23 daniel 800: ret = xmlStrcat(ret, node->content);
1.70 daniel 801: #else
802: ret = xmlStrcat(ret, xmlBufferContent(node->content));
803: #endif
804: } else {
1.61 daniel 805: xmlChar *buffer;
1.45 daniel 806:
1.70 daniel 807: #ifndef XML_USE_BUFFER_CONTENT
1.46 daniel 808: buffer = xmlEncodeEntitiesReentrant(doc, node->content);
1.70 daniel 809: #else
810: buffer = xmlEncodeEntitiesReentrant(doc,
811: xmlBufferContent(node->content));
812: #endif
1.45 daniel 813: if (buffer != NULL) {
814: ret = xmlStrcat(ret, buffer);
1.57 daniel 815: xmlFree(buffer);
1.45 daniel 816: }
817: }
1.23 daniel 818: } else if (node->type == XML_ENTITY_REF_NODE) {
819: if (inLine) {
820: ent = xmlGetDocEntity(doc, node->name);
821: if (ent != NULL)
822: ret = xmlStrcat(ret, ent->content);
1.70 daniel 823: else {
824: #ifndef XML_USE_BUFFER_CONTENT
1.23 daniel 825: ret = xmlStrcat(ret, node->content);
1.70 daniel 826: #else
827: ret = xmlStrcat(ret, xmlBufferContent(node->content));
828: #endif
829: }
1.23 daniel 830: } else {
1.61 daniel 831: xmlChar buf[2];
1.23 daniel 832: buf[0] = '&'; buf[1] = 0;
833: ret = xmlStrncat(ret, buf, 1);
834: ret = xmlStrcat(ret, node->name);
835: buf[0] = ';'; buf[1] = 0;
836: ret = xmlStrncat(ret, buf, 1);
837: }
1.24 daniel 838: }
839: #if 0
840: else {
841: fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
1.23 daniel 842: node->type);
843: }
1.24 daniel 844: #endif
1.23 daniel 845: node = node->next;
846: }
847: return(ret);
848: }
849:
850: /**
1.108 daniel 851: * xmlNodeListGetRawString:
852: * @doc: the document
853: * @list: a Node list
854: * @inLine: should we replace entity contents or show their external form
855: *
856: * Returns the string equivalent to the text contained in the Node list
857: * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
858: * this function doesn't do any character encoding handling.
859: *
860: * Returns a pointer to the string copy, the calller must free it.
861: */
862: xmlChar *
863: xmlNodeListGetRawString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
864: xmlNodePtr node = list;
865: xmlChar *ret = NULL;
866: xmlEntityPtr ent;
867:
868: if (list == NULL) return(NULL);
869:
870: while (node != NULL) {
871: if (node->type == XML_TEXT_NODE) {
872: if (inLine) {
873: #ifndef XML_USE_BUFFER_CONTENT
874: ret = xmlStrcat(ret, node->content);
875: #else
876: ret = xmlStrcat(ret, xmlBufferContent(node->content));
877: #endif
878: } else {
879: xmlChar *buffer;
880:
881: #ifndef XML_USE_BUFFER_CONTENT
882: buffer = xmlEncodeSpecialChars(doc, node->content);
883: #else
884: buffer = xmlEncodeSpecialChars(doc,
885: xmlBufferContent(node->content));
886: #endif
887: if (buffer != NULL) {
888: ret = xmlStrcat(ret, buffer);
889: xmlFree(buffer);
890: }
891: }
892: } else if (node->type == XML_ENTITY_REF_NODE) {
893: if (inLine) {
894: ent = xmlGetDocEntity(doc, node->name);
895: if (ent != NULL)
896: ret = xmlStrcat(ret, ent->content);
897: else {
898: #ifndef XML_USE_BUFFER_CONTENT
899: ret = xmlStrcat(ret, node->content);
900: #else
901: ret = xmlStrcat(ret, xmlBufferContent(node->content));
902: #endif
903: }
904: } else {
905: xmlChar buf[2];
906: buf[0] = '&'; buf[1] = 0;
907: ret = xmlStrncat(ret, buf, 1);
908: ret = xmlStrcat(ret, node->name);
909: buf[0] = ';'; buf[1] = 0;
910: ret = xmlStrncat(ret, buf, 1);
911: }
912: }
913: #if 0
914: else {
915: fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
916: node->type);
917: }
918: #endif
919: node = node->next;
920: }
921: return(ret);
922: }
923:
924: /**
1.23 daniel 925: * xmlNewProp:
926: * @node: the holding node
927: * @name: the name of the attribute
928: * @value: the value of the attribute
929: *
930: * Create a new property carried by a node.
1.36 daniel 931: * Returns a pointer to the attribute
1.1 veillard 932: */
1.28 daniel 933: xmlAttrPtr
1.61 daniel 934: xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
1.20 daniel 935: xmlAttrPtr cur;
1.1 veillard 936:
937: if (name == NULL) {
1.86 daniel 938: #ifdef DEBUG_TREE
1.1 veillard 939: fprintf(stderr, "xmlNewProp : name == NULL\n");
1.86 daniel 940: #endif
1.1 veillard 941: return(NULL);
942: }
943:
944: /*
945: * Allocate a new property and fill the fields.
946: */
1.57 daniel 947: cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1.1 veillard 948: if (cur == NULL) {
949: fprintf(stderr, "xmlNewProp : malloc failed\n");
950: return(NULL);
951: }
1.90 daniel 952: memset(cur, 0, sizeof(xmlAttr));
953: cur->type = XML_ATTRIBUTE_NODE;
1.1 veillard 954:
1.90 daniel 955: cur->parent = node;
1.56 daniel 956: cur->name = xmlStrdup(name);
1.67 daniel 957: if (value != NULL) {
958: xmlChar *buffer;
1.94 daniel 959: xmlNodePtr tmp;
960:
1.67 daniel 961: buffer = xmlEncodeEntitiesReentrant(node->doc, value);
1.90 daniel 962: cur->children = xmlStringGetNodeList(node->doc, buffer);
1.94 daniel 963: tmp = cur->children;
964: while (tmp != NULL) {
965: tmp->parent = (xmlNodePtr) cur;
966: if (tmp->next == NULL)
967: cur->last = tmp;
968: tmp = tmp->next;
969: }
1.67 daniel 970: xmlFree(buffer);
971: }
1.56 daniel 972:
973: /*
974: * Add it at the end to preserve parsing order ...
975: */
976: if (node != NULL) {
977: if (node->properties == NULL) {
978: node->properties = cur;
979: } else {
980: xmlAttrPtr prev = node->properties;
981:
982: while (prev->next != NULL) prev = prev->next;
983: prev->next = cur;
1.94 daniel 984: cur->prev = prev;
1.56 daniel 985: }
986: }
987: return(cur);
988: }
989:
990: /**
991: * xmlNewNsProp:
992: * @node: the holding node
993: * @ns: the namespace
994: * @name: the name of the attribute
995: * @value: the value of the attribute
996: *
997: * Create a new property tagged with a namespace and carried by a node.
998: * Returns a pointer to the attribute
999: */
1000: xmlAttrPtr
1.61 daniel 1001: xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
1002: const xmlChar *value) {
1.56 daniel 1003: xmlAttrPtr cur;
1004:
1005: if (name == NULL) {
1.86 daniel 1006: #ifdef DEBUG_TREE
1.56 daniel 1007: fprintf(stderr, "xmlNewProp : name == NULL\n");
1.86 daniel 1008: #endif
1.56 daniel 1009: return(NULL);
1010: }
1011:
1012: /*
1013: * Allocate a new property and fill the fields.
1014: */
1.57 daniel 1015: cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1.56 daniel 1016: if (cur == NULL) {
1017: fprintf(stderr, "xmlNewProp : malloc failed\n");
1018: return(NULL);
1019: }
1.90 daniel 1020: memset(cur, 0, sizeof(xmlAttr));
1021: cur->type = XML_ATTRIBUTE_NODE;
1.56 daniel 1022:
1.90 daniel 1023: cur->parent = node;
1.94 daniel 1024: if (node != NULL)
1025: cur->doc = node->doc;
1.56 daniel 1026: cur->ns = ns;
1.7 veillard 1027: cur->name = xmlStrdup(name);
1.94 daniel 1028: if (value != NULL) {
1029: xmlChar *buffer;
1030: xmlNodePtr tmp;
1031:
1032: buffer = xmlEncodeEntitiesReentrant(node->doc, value);
1033: cur->children = xmlStringGetNodeList(node->doc, buffer);
1034: tmp = cur->children;
1035: while (tmp != NULL) {
1036: tmp->parent = (xmlNodePtr) cur;
1037: if (tmp->next == NULL)
1038: cur->last = tmp;
1039: tmp = tmp->next;
1040: }
1041: xmlFree(buffer);
1042: }
1.17 daniel 1043:
1044: /*
1045: * Add it at the end to preserve parsing order ...
1046: */
1.1 veillard 1047: if (node != NULL) {
1.17 daniel 1048: if (node->properties == NULL) {
1049: node->properties = cur;
1050: } else {
1.20 daniel 1051: xmlAttrPtr prev = node->properties;
1.17 daniel 1052:
1053: while (prev->next != NULL) prev = prev->next;
1054: prev->next = cur;
1.94 daniel 1055: cur->prev = prev;
1.17 daniel 1056: }
1057: }
1.1 veillard 1058: return(cur);
1059: }
1060:
1.23 daniel 1061: /**
1062: * xmlNewDocProp:
1063: * @doc: the document
1064: * @name: the name of the attribute
1065: * @value: the value of the attribute
1066: *
1067: * Create a new property carried by a document.
1.36 daniel 1068: * Returns a pointer to the attribute
1.23 daniel 1069: */
1.28 daniel 1070: xmlAttrPtr
1.61 daniel 1071: xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
1.23 daniel 1072: xmlAttrPtr cur;
1073:
1074: if (name == NULL) {
1.86 daniel 1075: #ifdef DEBUG_TREE
1.23 daniel 1076: fprintf(stderr, "xmlNewProp : name == NULL\n");
1.86 daniel 1077: #endif
1.23 daniel 1078: return(NULL);
1079: }
1080:
1081: /*
1082: * Allocate a new property and fill the fields.
1083: */
1.57 daniel 1084: cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1.23 daniel 1085: if (cur == NULL) {
1086: fprintf(stderr, "xmlNewProp : malloc failed\n");
1087: return(NULL);
1088: }
1.90 daniel 1089: memset(cur, 0, sizeof(xmlAttr));
1090: cur->type = XML_ATTRIBUTE_NODE;
1.23 daniel 1091:
1092: cur->name = xmlStrdup(name);
1.94 daniel 1093: cur->doc = doc;
1.23 daniel 1094: if (value != NULL)
1.90 daniel 1095: cur->children = xmlStringGetNodeList(doc, value);
1.23 daniel 1096: return(cur);
1097: }
1098:
1099: /**
1100: * xmlFreePropList:
1101: * @cur: the first property in the list
1102: *
1.90 daniel 1103: * Free a property and all its siblings, all the children are freed too.
1.1 veillard 1104: */
1.28 daniel 1105: void
1106: xmlFreePropList(xmlAttrPtr cur) {
1.20 daniel 1107: xmlAttrPtr next;
1.1 veillard 1108: if (cur == NULL) {
1.86 daniel 1109: #ifdef DEBUG_TREE
1.1 veillard 1110: fprintf(stderr, "xmlFreePropList : property == NULL\n");
1.86 daniel 1111: #endif
1.1 veillard 1112: return;
1113: }
1114: while (cur != NULL) {
1115: next = cur->next;
1116: xmlFreeProp(cur);
1117: cur = next;
1118: }
1119: }
1120:
1.23 daniel 1121: /**
1122: * xmlFreeProp:
1.83 daniel 1123: * @cur: an attribute
1.23 daniel 1124: *
1.83 daniel 1125: * Free one attribute, all the content is freed too
1.1 veillard 1126: */
1.28 daniel 1127: void
1128: xmlFreeProp(xmlAttrPtr cur) {
1.1 veillard 1129: if (cur == NULL) {
1.86 daniel 1130: #ifdef DEBUG_TREE
1.1 veillard 1131: fprintf(stderr, "xmlFreeProp : property == NULL\n");
1.86 daniel 1132: #endif
1.1 veillard 1133: return;
1134: }
1.84 daniel 1135: /* Check for ID removal -> leading to invalid references ! */
1.90 daniel 1136: if ((cur->parent != NULL) &&
1137: (xmlIsID(cur->parent->doc, cur->parent, cur)))
1138: xmlRemoveID(cur->parent->doc, cur);
1.57 daniel 1139: if (cur->name != NULL) xmlFree((char *) cur->name);
1.90 daniel 1140: if (cur->children != NULL) xmlFreeNodeList(cur->children);
1.20 daniel 1141: memset(cur, -1, sizeof(xmlAttr));
1.57 daniel 1142: xmlFree(cur);
1.83 daniel 1143: }
1144:
1145: /**
1146: * xmlRemoveProp:
1147: * @cur: an attribute
1148: *
1149: * Unlink and free one attribute, all the content is freed too
1150: * Note this doesn't work for namespace definition attributes
1151: *
1152: * Returns 0 if success and -1 in case of error.
1153: */
1154: int
1155: xmlRemoveProp(xmlAttrPtr cur) {
1156: xmlAttrPtr tmp;
1157: if (cur == NULL) {
1.86 daniel 1158: #ifdef DEBUG_TREE
1.83 daniel 1159: fprintf(stderr, "xmlRemoveProp : cur == NULL\n");
1.86 daniel 1160: #endif
1.83 daniel 1161: return(-1);
1162: }
1.90 daniel 1163: if (cur->parent == NULL) {
1.94 daniel 1164: #ifdef DEBUG_TREE
1.90 daniel 1165: fprintf(stderr, "xmlRemoveProp : cur->parent == NULL\n");
1.86 daniel 1166: #endif
1.83 daniel 1167: return(-1);
1168: }
1.90 daniel 1169: tmp = cur->parent->properties;
1.83 daniel 1170: if (tmp == cur) {
1.90 daniel 1171: cur->parent->properties = cur->next;
1.83 daniel 1172: xmlFreeProp(cur);
1173: return(0);
1174: }
1175: while (tmp != NULL) {
1176: if (tmp->next == cur) {
1177: tmp->next = cur->next;
1.94 daniel 1178: if (tmp->next != NULL)
1179: tmp->next->prev = tmp;
1.83 daniel 1180: xmlFreeProp(cur);
1181: return(0);
1182: }
1183: tmp = tmp->next;
1184: }
1.86 daniel 1185: #ifdef DEBUG_TREE
1.83 daniel 1186: fprintf(stderr, "xmlRemoveProp : attribute not owned by its node\n");
1.86 daniel 1187: #endif
1.83 daniel 1188: return(-1);
1.1 veillard 1189: }
1190:
1.23 daniel 1191: /**
1.52 daniel 1192: * xmlNewPI:
1193: * @name: the processing instruction name
1194: * @content: the PI content
1195: *
1196: * Creation of a processing instruction element.
1197: * Returns a pointer to the new node object.
1198: */
1199: xmlNodePtr
1.61 daniel 1200: xmlNewPI(const xmlChar *name, const xmlChar *content) {
1.52 daniel 1201: xmlNodePtr cur;
1202:
1203: if (name == NULL) {
1.86 daniel 1204: #ifdef DEBUG_TREE
1.52 daniel 1205: fprintf(stderr, "xmlNewPI : name == NULL\n");
1.86 daniel 1206: #endif
1.52 daniel 1207: return(NULL);
1208: }
1209:
1210: /*
1211: * Allocate a new node and fill the fields.
1212: */
1.57 daniel 1213: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.52 daniel 1214: if (cur == NULL) {
1215: fprintf(stderr, "xmlNewPI : malloc failed\n");
1216: return(NULL);
1217: }
1.90 daniel 1218: memset(cur, 0, sizeof(xmlNode));
1219: cur->type = XML_PI_NODE;
1.52 daniel 1220:
1221: cur->name = xmlStrdup(name);
1.70 daniel 1222: if (content != NULL) {
1223: #ifndef XML_USE_BUFFER_CONTENT
1.52 daniel 1224: cur->content = xmlStrdup(content);
1.70 daniel 1225: #else
1226: cur->content = xmlBufferCreateSize(0);
1227: xmlBufferSetAllocationScheme(cur->content,
1228: xmlGetBufferAllocationScheme());
1229: xmlBufferAdd(cur->content, content, -1);
1230: #endif
1.90 daniel 1231: }
1.52 daniel 1232: return(cur);
1233: }
1234:
1235: /**
1.23 daniel 1236: * xmlNewNode:
1237: * @ns: namespace if any
1238: * @name: the node name
1239: *
1.120 veillard 1240: * Creation of a new node element. @ns is optionnal (NULL).
1241: *
1.36 daniel 1242: * Returns a pointer to the new node object.
1.1 veillard 1243: */
1.28 daniel 1244: xmlNodePtr
1.61 daniel 1245: xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
1.1 veillard 1246: xmlNodePtr cur;
1247:
1248: if (name == NULL) {
1.86 daniel 1249: #ifdef DEBUG_TREE
1.1 veillard 1250: fprintf(stderr, "xmlNewNode : name == NULL\n");
1.86 daniel 1251: #endif
1.1 veillard 1252: return(NULL);
1253: }
1254:
1255: /*
1256: * Allocate a new node and fill the fields.
1257: */
1.57 daniel 1258: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.1 veillard 1259: if (cur == NULL) {
1260: fprintf(stderr, "xmlNewNode : malloc failed\n");
1261: return(NULL);
1262: }
1.90 daniel 1263: memset(cur, 0, sizeof(xmlNode));
1.23 daniel 1264: cur->type = XML_ELEMENT_NODE;
1.90 daniel 1265:
1.22 daniel 1266: cur->name = xmlStrdup(name);
1.16 daniel 1267: cur->ns = ns;
1.1 veillard 1268: return(cur);
1269: }
1270:
1.23 daniel 1271: /**
1272: * xmlNewDocNode:
1273: * @doc: the document
1274: * @ns: namespace if any
1275: * @name: the node name
1.68 daniel 1276: * @content: the XML text content if any
1.23 daniel 1277: *
1278: * Creation of a new node element within a document. @ns and @content
1279: * are optionnal (NULL).
1.68 daniel 1280: * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1281: * references, but XML special chars need to be escaped first by using
1282: * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
1283: * need entities support.
1284: *
1.36 daniel 1285: * Returns a pointer to the new node object.
1.23 daniel 1286: */
1.28 daniel 1287: xmlNodePtr
1288: xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
1.68 daniel 1289: const xmlChar *name, const xmlChar *content) {
1.23 daniel 1290: xmlNodePtr cur;
1291:
1.24 daniel 1292: cur = xmlNewNode(ns, name);
1293: if (cur != NULL) {
1294: cur->doc = doc;
1.32 daniel 1295: if (content != NULL) {
1.90 daniel 1296: cur->children = xmlStringGetNodeList(doc, content);
1.34 daniel 1297: UPDATE_LAST_CHILD(cur)
1.32 daniel 1298: }
1.24 daniel 1299: }
1.23 daniel 1300: return(cur);
1301: }
1302:
1303:
1304: /**
1.68 daniel 1305: * xmlNewDocRawNode:
1306: * @doc: the document
1307: * @ns: namespace if any
1308: * @name: the node name
1309: * @content: the text content if any
1310: *
1311: * Creation of a new node element within a document. @ns and @content
1312: * are optionnal (NULL).
1313: *
1314: * Returns a pointer to the new node object.
1315: */
1316: xmlNodePtr
1317: xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns,
1318: const xmlChar *name, const xmlChar *content) {
1319: xmlNodePtr cur;
1320:
1321: cur = xmlNewNode(ns, name);
1322: if (cur != NULL) {
1323: cur->doc = doc;
1324: if (content != NULL) {
1.90 daniel 1325: cur->children = xmlNewDocText(doc, content);
1.68 daniel 1326: UPDATE_LAST_CHILD(cur)
1327: }
1328: }
1329: return(cur);
1330: }
1331:
1.85 daniel 1332: /**
1333: * xmlNewDocFragment:
1334: * @doc: the document owning the fragment
1335: *
1336: * Creation of a new Fragment node.
1337: * Returns a pointer to the new node object.
1338: */
1339: xmlNodePtr
1340: xmlNewDocFragment(xmlDocPtr doc) {
1341: xmlNodePtr cur;
1342:
1343: /*
1344: * Allocate a new DocumentFragment node and fill the fields.
1345: */
1346: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1347: if (cur == NULL) {
1348: fprintf(stderr, "xmlNewDocFragment : malloc failed\n");
1349: return(NULL);
1350: }
1.90 daniel 1351: memset(cur, 0, sizeof(xmlNode));
1352: cur->type = XML_DOCUMENT_FRAG_NODE;
1.85 daniel 1353:
1354: cur->doc = doc;
1355: return(cur);
1356: }
1.68 daniel 1357:
1358: /**
1.23 daniel 1359: * xmlNewText:
1360: * @content: the text content
1361: *
1362: * Creation of a new text node.
1.36 daniel 1363: * Returns a pointer to the new node object.
1.3 veillard 1364: */
1.28 daniel 1365: xmlNodePtr
1.61 daniel 1366: xmlNewText(const xmlChar *content) {
1.3 veillard 1367: xmlNodePtr cur;
1368:
1369: /*
1370: * Allocate a new node and fill the fields.
1371: */
1.57 daniel 1372: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.3 veillard 1373: if (cur == NULL) {
1.19 daniel 1374: fprintf(stderr, "xmlNewText : malloc failed\n");
1.3 veillard 1375: return(NULL);
1376: }
1.90 daniel 1377: memset(cur, 0, sizeof(xmlNode));
1378: cur->type = XML_TEXT_NODE;
1.3 veillard 1379:
1.18 daniel 1380: cur->name = xmlStrdup(xmlStringText);
1.70 daniel 1381: if (content != NULL) {
1382: #ifndef XML_USE_BUFFER_CONTENT
1.7 veillard 1383: cur->content = xmlStrdup(content);
1.70 daniel 1384: #else
1385: cur->content = xmlBufferCreateSize(0);
1386: xmlBufferSetAllocationScheme(cur->content,
1387: xmlGetBufferAllocationScheme());
1388: xmlBufferAdd(cur->content, content, -1);
1389: #endif
1.90 daniel 1390: }
1.3 veillard 1391: return(cur);
1392: }
1393:
1.23 daniel 1394: /**
1.68 daniel 1395: * xmlNewTextChild:
1396: * @parent: the parent node
1397: * @ns: a namespace if any
1398: * @name: the name of the child
1399: * @content: the text content of the child if any.
1400: *
1.90 daniel 1401: * Creation of a new child element, added at the end of @parent children list.
1.68 daniel 1402: * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1403: * a child TEXT node will be created containing the string content.
1404: *
1405: * Returns a pointer to the new node object.
1406: */
1407: xmlNodePtr
1408: xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns,
1409: const xmlChar *name, const xmlChar *content) {
1410: xmlNodePtr cur, prev;
1411:
1412: if (parent == NULL) {
1.86 daniel 1413: #ifdef DEBUG_TREE
1.68 daniel 1414: fprintf(stderr, "xmlNewTextChild : parent == NULL\n");
1.86 daniel 1415: #endif
1.68 daniel 1416: return(NULL);
1417: }
1418:
1419: if (name == NULL) {
1.86 daniel 1420: #ifdef DEBUG_TREE
1.68 daniel 1421: fprintf(stderr, "xmlNewTextChild : name == NULL\n");
1.86 daniel 1422: #endif
1.68 daniel 1423: return(NULL);
1424: }
1425:
1426: /*
1427: * Allocate a new node
1428: */
1429: if (ns == NULL)
1430: cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content);
1431: else
1432: cur = xmlNewDocRawNode(parent->doc, ns, name, content);
1433: if (cur == NULL) return(NULL);
1434:
1435: /*
1.90 daniel 1436: * add the new element at the end of the children list.
1.68 daniel 1437: */
1438: cur->type = XML_ELEMENT_NODE;
1439: cur->parent = parent;
1440: cur->doc = parent->doc;
1.90 daniel 1441: if (parent->children == NULL) {
1442: parent->children = cur;
1.68 daniel 1443: parent->last = cur;
1444: } else {
1445: prev = parent->last;
1446: prev->next = cur;
1447: cur->prev = prev;
1448: parent->last = cur;
1449: }
1450:
1451: return(cur);
1452: }
1453:
1454: /**
1.88 daniel 1455: * xmlNewCharRef:
1456: * @doc: the document
1457: * @name: the char ref string, starting with # or "&# ... ;"
1458: *
1459: * Creation of a new character reference node.
1460: * Returns a pointer to the new node object.
1461: */
1462: xmlNodePtr
1463: xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) {
1464: xmlNodePtr cur;
1465:
1466: /*
1467: * Allocate a new node and fill the fields.
1468: */
1469: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1470: if (cur == NULL) {
1471: fprintf(stderr, "xmlNewText : malloc failed\n");
1472: return(NULL);
1473: }
1.90 daniel 1474: memset(cur, 0, sizeof(xmlNode));
1475: cur->type = XML_ENTITY_REF_NODE;
1.88 daniel 1476:
1477: cur->doc = doc;
1478: if (name[0] == '&') {
1479: int len;
1480: name++;
1481: len = xmlStrlen(name);
1482: if (name[len - 1] == ';')
1483: cur->name = xmlStrndup(name, len - 1);
1484: else
1485: cur->name = xmlStrndup(name, len);
1486: } else
1487: cur->name = xmlStrdup(name);
1488: return(cur);
1489: }
1490:
1491: /**
1.23 daniel 1492: * xmlNewReference:
1493: * @doc: the document
1494: * @name: the reference name, or the reference string with & and ;
1495: *
1496: * Creation of a new reference node.
1.36 daniel 1497: * Returns a pointer to the new node object.
1.23 daniel 1498: */
1.28 daniel 1499: xmlNodePtr
1.61 daniel 1500: xmlNewReference(xmlDocPtr doc, const xmlChar *name) {
1.23 daniel 1501: xmlNodePtr cur;
1502: xmlEntityPtr ent;
1503:
1504: /*
1505: * Allocate a new node and fill the fields.
1506: */
1.57 daniel 1507: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.23 daniel 1508: if (cur == NULL) {
1509: fprintf(stderr, "xmlNewText : malloc failed\n");
1510: return(NULL);
1511: }
1.90 daniel 1512: memset(cur, 0, sizeof(xmlNode));
1513: cur->type = XML_ENTITY_REF_NODE;
1.23 daniel 1514:
1.28 daniel 1515: cur->doc = doc;
1.23 daniel 1516: if (name[0] == '&') {
1517: int len;
1518: name++;
1519: len = xmlStrlen(name);
1520: if (name[len - 1] == ';')
1521: cur->name = xmlStrndup(name, len - 1);
1522: else
1523: cur->name = xmlStrndup(name, len);
1524: } else
1525: cur->name = xmlStrdup(name);
1526:
1527: ent = xmlGetDocEntity(doc, cur->name);
1.70 daniel 1528: if (ent != NULL) {
1529: #ifndef XML_USE_BUFFER_CONTENT
1.23 daniel 1530: cur->content = ent->content;
1.70 daniel 1531: #else
1532: /*
1533: * CJN 11.18.99 this might be a problem, since the xmlBuffer gets
1534: * a copy of this pointer. Let's hope we don't manipulate it
1535: * later
1536: */
1537: cur->content = xmlBufferCreateSize(0);
1538: xmlBufferSetAllocationScheme(cur->content,
1539: xmlGetBufferAllocationScheme());
1540: if (ent->content != NULL)
1541: xmlBufferAdd(cur->content, ent->content, -1);
1542: #endif
1.99 daniel 1543: cur->children = (xmlNodePtr) ent;
1.90 daniel 1544: }
1.23 daniel 1545: return(cur);
1546: }
1547:
1548: /**
1549: * xmlNewDocText:
1550: * @doc: the document
1551: * @content: the text content
1552: *
1553: * Creation of a new text node within a document.
1.36 daniel 1554: * Returns a pointer to the new node object.
1.23 daniel 1555: */
1.28 daniel 1556: xmlNodePtr
1.61 daniel 1557: xmlNewDocText(xmlDocPtr doc, const xmlChar *content) {
1.23 daniel 1558: xmlNodePtr cur;
1559:
1560: cur = xmlNewText(content);
1561: if (cur != NULL) cur->doc = doc;
1562: return(cur);
1563: }
1564:
1565: /**
1566: * xmlNewTextLen:
1567: * @content: the text content
1568: * @len: the text len.
1569: *
1570: * Creation of a new text node with an extra parameter for the content's lenght
1.36 daniel 1571: * Returns a pointer to the new node object.
1.21 daniel 1572: */
1.28 daniel 1573: xmlNodePtr
1.61 daniel 1574: xmlNewTextLen(const xmlChar *content, int len) {
1.21 daniel 1575: xmlNodePtr cur;
1576:
1577: /*
1578: * Allocate a new node and fill the fields.
1579: */
1.57 daniel 1580: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.21 daniel 1581: if (cur == NULL) {
1582: fprintf(stderr, "xmlNewText : malloc failed\n");
1583: return(NULL);
1584: }
1.90 daniel 1585: memset(cur, 0, sizeof(xmlNode));
1586: cur->type = XML_TEXT_NODE;
1.21 daniel 1587:
1588: cur->name = xmlStrdup(xmlStringText);
1.70 daniel 1589: if (content != NULL) {
1590: #ifndef XML_USE_BUFFER_CONTENT
1.21 daniel 1591: cur->content = xmlStrndup(content, len);
1.70 daniel 1592: #else
1593: cur->content = xmlBufferCreateSize(len);
1594: xmlBufferSetAllocationScheme(cur->content,
1595: xmlGetBufferAllocationScheme());
1596: xmlBufferAdd(cur->content, content, len);
1597: #endif
1.90 daniel 1598: }
1.21 daniel 1599: return(cur);
1600: }
1601:
1.23 daniel 1602: /**
1603: * xmlNewDocTextLen:
1604: * @doc: the document
1605: * @content: the text content
1606: * @len: the text len.
1607: *
1608: * Creation of a new text node with an extra content lenght parameter. The
1609: * text node pertain to a given document.
1.36 daniel 1610: * Returns a pointer to the new node object.
1.23 daniel 1611: */
1.28 daniel 1612: xmlNodePtr
1.61 daniel 1613: xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) {
1.23 daniel 1614: xmlNodePtr cur;
1615:
1616: cur = xmlNewTextLen(content, len);
1617: if (cur != NULL) cur->doc = doc;
1618: return(cur);
1619: }
1620:
1621: /**
1622: * xmlNewComment:
1623: * @content: the comment content
1624: *
1625: * Creation of a new node containing a comment.
1.36 daniel 1626: * Returns a pointer to the new node object.
1.14 daniel 1627: */
1.28 daniel 1628: xmlNodePtr
1.61 daniel 1629: xmlNewComment(const xmlChar *content) {
1.14 daniel 1630: xmlNodePtr cur;
1631:
1632: /*
1633: * Allocate a new node and fill the fields.
1634: */
1.57 daniel 1635: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.14 daniel 1636: if (cur == NULL) {
1.19 daniel 1637: fprintf(stderr, "xmlNewComment : malloc failed\n");
1.14 daniel 1638: return(NULL);
1639: }
1.90 daniel 1640: memset(cur, 0, sizeof(xmlNode));
1641: cur->type = XML_COMMENT_NODE;
1.14 daniel 1642:
1.90 daniel 1643: cur->name = xmlStrdup(xmlStringComment);
1.70 daniel 1644: if (content != NULL) {
1645: #ifndef XML_USE_BUFFER_CONTENT
1.14 daniel 1646: cur->content = xmlStrdup(content);
1.70 daniel 1647: #else
1648: cur->content = xmlBufferCreateSize(0);
1649: xmlBufferSetAllocationScheme(cur->content,
1650: xmlGetBufferAllocationScheme());
1651: xmlBufferAdd(cur->content, content, -1);
1652: #endif
1.90 daniel 1653: }
1.14 daniel 1654: return(cur);
1655: }
1656:
1.23 daniel 1657: /**
1.50 daniel 1658: * xmlNewCDataBlock:
1659: * @doc: the document
1660: * @content: the CData block content content
1661: * @len: the length of the block
1662: *
1663: * Creation of a new node containing a CData block.
1664: * Returns a pointer to the new node object.
1665: */
1666: xmlNodePtr
1.61 daniel 1667: xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) {
1.50 daniel 1668: xmlNodePtr cur;
1669:
1670: /*
1671: * Allocate a new node and fill the fields.
1672: */
1.57 daniel 1673: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.50 daniel 1674: if (cur == NULL) {
1675: fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1676: return(NULL);
1677: }
1.90 daniel 1678: memset(cur, 0, sizeof(xmlNode));
1679: cur->type = XML_CDATA_SECTION_NODE;
1.50 daniel 1680:
1.70 daniel 1681: if (content != NULL) {
1682: #ifndef XML_USE_BUFFER_CONTENT
1.50 daniel 1683: cur->content = xmlStrndup(content, len);
1.70 daniel 1684: #else
1685: cur->content = xmlBufferCreateSize(len);
1686: xmlBufferSetAllocationScheme(cur->content,
1687: xmlGetBufferAllocationScheme());
1688: xmlBufferAdd(cur->content, content, len);
1689: #endif
1.90 daniel 1690: }
1.50 daniel 1691: return(cur);
1692: }
1693:
1694: /**
1.36 daniel 1695: * xmlNewDocComment:
1.23 daniel 1696: * @doc: the document
1697: * @content: the comment content
1698: *
1699: * Creation of a new node containing a commentwithin a document.
1.36 daniel 1700: * Returns a pointer to the new node object.
1.23 daniel 1701: */
1.28 daniel 1702: xmlNodePtr
1.61 daniel 1703: xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) {
1.23 daniel 1704: xmlNodePtr cur;
1705:
1706: cur = xmlNewComment(content);
1707: if (cur != NULL) cur->doc = doc;
1708: return(cur);
1709: }
1710:
1.68 daniel 1711:
1.23 daniel 1712: /**
1713: * xmlNewChild:
1714: * @parent: the parent node
1715: * @ns: a namespace if any
1716: * @name: the name of the child
1.68 daniel 1717: * @content: the XML content of the child if any.
1.23 daniel 1718: *
1.90 daniel 1719: * Creation of a new child element, added at the end of @parent children list.
1.24 daniel 1720: * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1721: * a child list containing the TEXTs and ENTITY_REFs node will be created.
1.68 daniel 1722: * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
1723: * references, but XML special chars need to be escaped first by using
1724: * xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities
1725: * support is not needed.
1726: *
1.36 daniel 1727: * Returns a pointer to the new node object.
1.1 veillard 1728: */
1.28 daniel 1729: xmlNodePtr
1730: xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
1.68 daniel 1731: const xmlChar *name, const xmlChar *content) {
1.1 veillard 1732: xmlNodePtr cur, prev;
1733:
1734: if (parent == NULL) {
1.86 daniel 1735: #ifdef DEBUG_TREE
1.1 veillard 1736: fprintf(stderr, "xmlNewChild : parent == NULL\n");
1.86 daniel 1737: #endif
1.1 veillard 1738: return(NULL);
1739: }
1740:
1741: if (name == NULL) {
1.86 daniel 1742: #ifdef DEBUG_TREE
1.1 veillard 1743: fprintf(stderr, "xmlNewChild : name == NULL\n");
1.86 daniel 1744: #endif
1.1 veillard 1745: return(NULL);
1746: }
1747:
1748: /*
1749: * Allocate a new node
1750: */
1.16 daniel 1751: if (ns == NULL)
1.24 daniel 1752: cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
1.1 veillard 1753: else
1.24 daniel 1754: cur = xmlNewDocNode(parent->doc, ns, name, content);
1.1 veillard 1755: if (cur == NULL) return(NULL);
1756:
1757: /*
1.90 daniel 1758: * add the new element at the end of the children list.
1.1 veillard 1759: */
1.25 daniel 1760: cur->type = XML_ELEMENT_NODE;
1.1 veillard 1761: cur->parent = parent;
1.23 daniel 1762: cur->doc = parent->doc;
1.90 daniel 1763: if (parent->children == NULL) {
1764: parent->children = cur;
1.32 daniel 1765: parent->last = cur;
1.1 veillard 1766: } else {
1.32 daniel 1767: prev = parent->last;
1.1 veillard 1768: prev->next = cur;
1.23 daniel 1769: cur->prev = prev;
1.32 daniel 1770: parent->last = cur;
1.1 veillard 1771: }
1772:
1773: return(cur);
1774: }
1775:
1.23 daniel 1776: /**
1.78 daniel 1777: * xmlAddNextSibling:
1778: * @cur: the child node
1779: * @elem: the new node
1780: *
1781: * Add a new element @elem as the next siblings of @cur
1782: * If the new element was already inserted in a document it is
1783: * first unlinked from its existing context.
1.131 veillard 1784: * As a result of text merging @elem may be freed.
1.78 daniel 1785: *
1786: * Returns the new element or NULL in case of error.
1787: */
1788: xmlNodePtr
1789: xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) {
1790: if (cur == NULL) {
1.86 daniel 1791: #ifdef DEBUG_TREE
1.78 daniel 1792: fprintf(stderr, "xmlAddNextSibling : cur == NULL\n");
1.86 daniel 1793: #endif
1.78 daniel 1794: return(NULL);
1795: }
1796: if (elem == NULL) {
1.86 daniel 1797: #ifdef DEBUG_TREE
1.78 daniel 1798: fprintf(stderr, "xmlAddNextSibling : elem == NULL\n");
1.86 daniel 1799: #endif
1.78 daniel 1800: return(NULL);
1801: }
1802:
1803: xmlUnlinkNode(elem);
1.131 veillard 1804:
1805: if (elem->type == XML_TEXT_NODE) {
1806: if (cur->type == XML_TEXT_NODE) {
1807: #ifndef XML_USE_BUFFER_CONTENT
1808: xmlNodeAddContent(cur, elem->content);
1809: #else
1810: xmlNodeAddContent(cur, xmlBufferContent(elem->content));
1811: #endif
1812: xmlFreeNode(elem);
1813: return(cur);
1814: }
1815: if ((cur->next != NULL) && (cur->type == XML_TEXT_NODE)) {
1816: #ifndef XML_USE_BUFFER_CONTENT
1817: xmlChar *tmp;
1818:
1819: tmp = xmlStrdup(elem->content);
1820: tmp = xmlStrcat(tmp, cur->next->content);
1821: xmlNodeSetContent(cur->next, tmp);
1822: xmlFree(tmp);
1823: #else
1824: xmlBufferAddHead(cur->next, xmlBufferContent(elem->content),
1825: xmlBufferLength(elem->content));
1826: #endif
1827: xmlFreeNode(elem);
1828: return(cur->next);
1829: }
1830: }
1831:
1.78 daniel 1832: elem->doc = cur->doc;
1833: elem->parent = cur->parent;
1.102 daniel 1834: elem->prev = cur;
1835: elem->next = cur->next;
1836: cur->next = elem;
1837: if (elem->next != NULL)
1838: elem->next->prev = elem;
1839: if ((elem->parent != NULL) && (elem->parent->last == cur))
1840: elem->parent->last = elem;
1.78 daniel 1841: return(elem);
1842: }
1843:
1844: /**
1845: * xmlAddPrevSibling:
1846: * @cur: the child node
1847: * @elem: the new node
1848: *
1849: * Add a new element @elem as the previous siblings of @cur
1.131 veillard 1850: * merging adjacent TEXT nodes (@elem may be freed)
1.78 daniel 1851: * If the new element was already inserted in a document it is
1852: * first unlinked from its existing context.
1853: *
1854: * Returns the new element or NULL in case of error.
1855: */
1856: xmlNodePtr
1857: xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) {
1858: if (cur == NULL) {
1.86 daniel 1859: #ifdef DEBUG_TREE
1.78 daniel 1860: fprintf(stderr, "xmlAddPrevSibling : cur == NULL\n");
1.86 daniel 1861: #endif
1.78 daniel 1862: return(NULL);
1863: }
1864: if (elem == NULL) {
1.86 daniel 1865: #ifdef DEBUG_TREE
1.78 daniel 1866: fprintf(stderr, "xmlAddPrevSibling : elem == NULL\n");
1.86 daniel 1867: #endif
1.78 daniel 1868: return(NULL);
1869: }
1870:
1871: xmlUnlinkNode(elem);
1.131 veillard 1872:
1873: if (elem->type == XML_TEXT_NODE) {
1874: if (cur->type == XML_TEXT_NODE) {
1875: #ifndef XML_USE_BUFFER_CONTENT
1876: xmlChar *tmp;
1877:
1878: tmp = xmlStrdup(elem->content);
1879: tmp = xmlStrcat(tmp, cur->content);
1880: xmlNodeSetContent(cur, tmp);
1881: xmlFree(tmp);
1882: #else
1883: xmlBufferAddHead(cur->content, xmlBufferContent(elem->content),
1884: xmlBufferLength(elem->content));
1885: #endif
1886: xmlFreeNode(elem);
1887: return(cur);
1888: }
1889: if ((cur->prev != NULL) && (cur->prev->type == XML_TEXT_NODE)) {
1890: #ifndef XML_USE_BUFFER_CONTENT
1891: xmlNodeAddContent(cur->prev, elem->content);
1892: #else
1893: xmlNodeAddContent(cur->prev, xmlBufferContent(elem->content));
1894: #endif
1895: xmlFreeNode(elem);
1896: return(cur->prev);
1897: }
1898: }
1899:
1.78 daniel 1900: elem->doc = cur->doc;
1901: elem->parent = cur->parent;
1.102 daniel 1902: elem->next = cur;
1903: elem->prev = cur->prev;
1904: cur->prev = elem;
1905: if (elem->prev != NULL)
1906: elem->prev->next = elem;
1907: if ((elem->parent != NULL) && (elem->parent->children == cur))
1908: elem->parent->children = elem;
1.78 daniel 1909: return(elem);
1910: }
1911:
1912: /**
1.52 daniel 1913: * xmlAddSibling:
1914: * @cur: the child node
1915: * @elem: the new node
1916: *
1.78 daniel 1917: * Add a new element @elem to the list of siblings of @cur
1.131 veillard 1918: * merging adjacent TEXT nodes (@elem may be freed)
1.78 daniel 1919: * If the new element was already inserted in a document it is
1920: * first unlinked from its existing context.
1921: *
1922: * Returns the new element or NULL in case of error.
1.52 daniel 1923: */
1924: xmlNodePtr
1925: xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1926: xmlNodePtr parent;
1927:
1928: if (cur == NULL) {
1.86 daniel 1929: #ifdef DEBUG_TREE
1.52 daniel 1930: fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1.86 daniel 1931: #endif
1.52 daniel 1932: return(NULL);
1933: }
1934:
1935: if (elem == NULL) {
1.86 daniel 1936: #ifdef DEBUG_TREE
1.52 daniel 1937: fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1.86 daniel 1938: #endif
1.52 daniel 1939: return(NULL);
1940: }
1941:
1.78 daniel 1942: /*
1943: * Constant time is we can rely on the ->parent->last to find
1944: * the last sibling.
1945: */
1946: if ((cur->parent != NULL) &&
1.90 daniel 1947: (cur->parent->children != NULL) &&
1.78 daniel 1948: (cur->parent->last != NULL) &&
1949: (cur->parent->last->next == NULL)) {
1950: cur = cur->parent->last;
1951: } else {
1952: while (cur->next != NULL) cur = cur->next;
1.52 daniel 1953: }
1954:
1.78 daniel 1955: xmlUnlinkNode(elem);
1.131 veillard 1956:
1957: if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE)) {
1958: #ifndef XML_USE_BUFFER_CONTENT
1959: xmlNodeAddContent(cur, elem->content);
1960: #else
1961: xmlNodeAddContent(cur, xmlBufferContent(elem->content));
1962: #endif
1963: xmlFreeNode(elem);
1964: return(cur);
1965: }
1966:
1.52 daniel 1967: if (elem->doc == NULL)
1968: elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1969:
1970: parent = cur->parent;
1971: elem->prev = cur;
1972: elem->next = NULL;
1973: elem->parent = parent;
1974: cur->next = elem;
1975: if (parent != NULL)
1976: parent->last = elem;
1977:
1978: return(elem);
1979: }
1980:
1981: /**
1.117 veillard 1982: * xmlAddChildList:
1983: * @parent: the parent node
1984: * @cur: the first node in the list
1985: *
1986: * Add a list of node at the end of the child list of the parent
1.131 veillard 1987: * merging adjacent TEXT nodes (@cur may be freed)
1.117 veillard 1988: *
1989: * Returns the last child or NULL in case of error.
1990: */
1991: xmlNodePtr
1992: xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) {
1993: xmlNodePtr prev;
1994:
1995: if (parent == NULL) {
1996: #ifdef DEBUG_TREE
1997: fprintf(stderr, "xmlAddChild : parent == NULL\n");
1998: #endif
1999: return(NULL);
2000: }
2001:
2002: if (cur == NULL) {
2003: #ifdef DEBUG_TREE
2004: fprintf(stderr, "xmlAddChild : child == NULL\n");
2005: #endif
2006: return(NULL);
2007: }
2008:
2009: if ((cur->doc != NULL) && (parent->doc != NULL) &&
2010: (cur->doc != parent->doc)) {
2011: #ifdef DEBUG_TREE
2012: fprintf(stderr, "Elements moved to a different document\n");
2013: #endif
2014: }
2015:
2016: /*
2017: * add the first element at the end of the children list.
2018: */
2019: if (parent->children == NULL) {
2020: parent->children = cur;
2021: } else {
1.131 veillard 2022: /*
2023: * If cur and parent->last both are TEXT nodes, then merge them.
2024: */
2025: if ((cur->type == XML_TEXT_NODE) &&
2026: (parent->last->type == XML_TEXT_NODE)) {
2027: #ifndef XML_USE_BUFFER_CONTENT
2028: xmlNodeAddContent(parent->last, cur->content);
2029: #else
2030: xmlNodeAddContent(parent->last, xmlBufferContent(cur->content));
2031: #endif
2032: /*
2033: * if it's the only child, nothing more to be done.
2034: */
2035: if (cur->next == NULL) {
2036: xmlFreeNode(cur);
2037: return(parent->last);
2038: }
2039: prev = cur;
2040: cur = cur->next;
2041: xmlFreeNode(prev);
2042: }
1.117 veillard 2043: prev = parent->last;
2044: prev->next = cur;
2045: cur->prev = prev;
2046: }
2047: while (cur->next != NULL) {
2048: cur->parent = parent;
2049: cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
2050: cur = cur->next;
2051: }
2052: cur->parent = parent;
2053: cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
2054: parent->last = cur;
2055:
2056: return(cur);
2057: }
2058:
2059: /**
1.23 daniel 2060: * xmlAddChild:
2061: * @parent: the parent node
2062: * @cur: the child node
2063: *
1.131 veillard 2064: * Add a new child element, to @parent, at the end of the child list
2065: * merging adjacent TEXT nodes (in which case @cur is freed)
1.36 daniel 2066: * Returns the child or NULL in case of error.
1.2 veillard 2067: */
1.28 daniel 2068: xmlNodePtr
2069: xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
1.2 veillard 2070: xmlNodePtr prev;
2071:
2072: if (parent == NULL) {
1.86 daniel 2073: #ifdef DEBUG_TREE
1.73 daniel 2074: fprintf(stderr, "xmlAddChild : parent == NULL\n");
1.86 daniel 2075: #endif
1.2 veillard 2076: return(NULL);
2077: }
2078:
2079: if (cur == NULL) {
1.86 daniel 2080: #ifdef DEBUG_TREE
1.73 daniel 2081: fprintf(stderr, "xmlAddChild : child == NULL\n");
1.86 daniel 2082: #endif
1.2 veillard 2083: return(NULL);
2084: }
2085:
1.23 daniel 2086: if ((cur->doc != NULL) && (parent->doc != NULL) &&
2087: (cur->doc != parent->doc)) {
1.86 daniel 2088: #ifdef DEBUG_TREE
1.23 daniel 2089: fprintf(stderr, "Elements moved to a different document\n");
1.86 daniel 2090: #endif
1.131 veillard 2091: }
2092:
2093: /*
2094: * If cur is a TEXT node, merge its content with adjacent TEXT nodes
2095: * or with parent->content if parent->content != NULL.
2096: * cur is then freed.
2097: */
2098: if (cur->type == XML_TEXT_NODE) {
2099: if (((parent->type == XML_ELEMENT_NODE) ||
2100: (parent->type == XML_TEXT_NODE)) &&
2101: (parent->content != NULL)) {
2102: #ifndef XML_USE_BUFFER_CONTENT
2103: xmlNodeAddContent(parent, cur->content);
2104: #else
2105: xmlNodeAddContent(parent, xmlBufferContent(cur->content));
2106: #endif
2107: xmlFreeNode(cur);
2108: return(parent);
2109: }
2110: if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE)) {
2111: #ifndef XML_USE_BUFFER_CONTENT
2112: xmlNodeAddContent(parent->last, cur->content);
2113: #else
2114: xmlNodeAddContent(parent->last, xmlBufferContent(cur->content));
2115: #endif
2116: xmlFreeNode(cur);
2117: return(parent->last);
2118: }
1.23 daniel 2119: }
2120:
1.2 veillard 2121: /*
1.90 daniel 2122: * add the new element at the end of the children list.
1.2 veillard 2123: */
2124: cur->parent = parent;
1.23 daniel 2125: cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
1.32 daniel 2126:
1.24 daniel 2127: /*
2128: * Handle the case where parent->content != NULL, in that case it will
2129: * create a intermediate TEXT node.
2130: */
1.93 daniel 2131: if (((parent->type == XML_ELEMENT_NODE) || (parent->type == XML_TEXT_NODE)) &&
2132: (parent->content != NULL)) {
1.24 daniel 2133: xmlNodePtr text;
2134:
1.70 daniel 2135: #ifndef XML_USE_BUFFER_CONTENT
1.24 daniel 2136: text = xmlNewDocText(parent->doc, parent->content);
1.70 daniel 2137: #else
2138: text = xmlNewDocText(parent->doc, xmlBufferContent(parent->content));
2139: #endif
1.24 daniel 2140: if (text != NULL) {
1.90 daniel 2141: text->next = parent->children;
1.24 daniel 2142: if (text->next != NULL)
2143: text->next->prev = text;
1.90 daniel 2144: parent->children = text;
1.34 daniel 2145: UPDATE_LAST_CHILD(parent)
1.70 daniel 2146: #ifndef XML_USE_BUFFER_CONTENT
1.57 daniel 2147: xmlFree(parent->content);
1.70 daniel 2148: #else
2149: xmlBufferFree(parent->content);
2150: #endif
1.24 daniel 2151: parent->content = NULL;
2152: }
2153: }
1.90 daniel 2154: if (parent->children == NULL) {
2155: parent->children = cur;
1.32 daniel 2156: parent->last = cur;
1.2 veillard 2157: } else {
1.32 daniel 2158: prev = parent->last;
1.2 veillard 2159: prev->next = cur;
1.23 daniel 2160: cur->prev = prev;
1.32 daniel 2161: parent->last = cur;
1.2 veillard 2162: }
2163:
2164: return(cur);
2165: }
2166:
1.23 daniel 2167: /**
2168: * xmlGetLastChild:
2169: * @parent: the parent node
2170: *
2171: * Search the last child of a node.
1.36 daniel 2172: * Returns the last child or NULL if none.
1.21 daniel 2173: */
1.28 daniel 2174: xmlNodePtr
2175: xmlGetLastChild(xmlNodePtr parent) {
1.21 daniel 2176: if (parent == NULL) {
1.86 daniel 2177: #ifdef DEBUG_TREE
1.21 daniel 2178: fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1.86 daniel 2179: #endif
1.21 daniel 2180: return(NULL);
2181: }
1.32 daniel 2182: return(parent->last);
1.21 daniel 2183: }
2184:
1.23 daniel 2185: /**
2186: * xmlFreeNodeList:
2187: * @cur: the first node in the list
2188: *
2189: * Free a node and all its siblings, this is a recursive behaviour, all
1.90 daniel 2190: * the children are freed too.
1.1 veillard 2191: */
1.28 daniel 2192: void
2193: xmlFreeNodeList(xmlNodePtr cur) {
1.1 veillard 2194: xmlNodePtr next;
2195: if (cur == NULL) {
1.86 daniel 2196: #ifdef DEBUG_TREE
1.1 veillard 2197: fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1.86 daniel 2198: #endif
1.1 veillard 2199: return;
2200: }
2201: while (cur != NULL) {
2202: next = cur->next;
2203: xmlFreeNode(cur);
2204: cur = next;
2205: }
2206: }
2207:
1.23 daniel 2208: /**
2209: * xmlFreeNode:
2210: * @cur: the node
2211: *
1.90 daniel 2212: * Free a node, this is a recursive behaviour, all the children are freed too.
1.97 daniel 2213: * This doesn't unlink the child from the list, use xmlUnlinkNode() first.
1.1 veillard 2214: */
1.28 daniel 2215: void
2216: xmlFreeNode(xmlNodePtr cur) {
1.1 veillard 2217: if (cur == NULL) {
1.86 daniel 2218: #ifdef DEBUG_TREE
1.1 veillard 2219: fprintf(stderr, "xmlFreeNode : node == NULL\n");
1.86 daniel 2220: #endif
1.1 veillard 2221: return;
2222: }
1.92 daniel 2223: if (cur->type == XML_DTD_NODE)
2224: return;
1.23 daniel 2225: cur->doc = NULL;
2226: cur->parent = NULL;
2227: cur->next = NULL;
2228: cur->prev = NULL;
1.99 daniel 2229: if ((cur->children != NULL) &&
2230: (cur->type != XML_ENTITY_REF_NODE))
2231: xmlFreeNodeList(cur->children);
1.1 veillard 2232: if (cur->properties != NULL) xmlFreePropList(cur->properties);
1.23 daniel 2233: if (cur->type != XML_ENTITY_REF_NODE)
1.70 daniel 2234: #ifndef XML_USE_BUFFER_CONTENT
1.57 daniel 2235: if (cur->content != NULL) xmlFree(cur->content);
1.70 daniel 2236: #else
2237: if (cur->content != NULL) xmlBufferFree(cur->content);
2238: #endif
1.57 daniel 2239: if (cur->name != NULL) xmlFree((char *) cur->name);
1.19 daniel 2240: if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1.1 veillard 2241: memset(cur, -1, sizeof(xmlNode));
1.57 daniel 2242: xmlFree(cur);
1.1 veillard 2243: }
2244:
1.28 daniel 2245: /**
2246: * xmlUnlinkNode:
2247: * @cur: the node
2248: *
2249: * Unlink a node from it's current context, the node is not freed
2250: */
2251: void
2252: xmlUnlinkNode(xmlNodePtr cur) {
2253: if (cur == NULL) {
1.86 daniel 2254: #ifdef DEBUG_TREE
1.28 daniel 2255: fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1.86 daniel 2256: #endif
1.28 daniel 2257: return;
2258: }
1.90 daniel 2259: if ((cur->parent != NULL) && (cur->parent->children == cur))
2260: cur->parent->children = cur->next;
1.32 daniel 2261: if ((cur->parent != NULL) && (cur->parent->last == cur))
2262: cur->parent->last = cur->prev;
1.28 daniel 2263: if (cur->next != NULL)
2264: cur->next->prev = cur->prev;
2265: if (cur->prev != NULL)
2266: cur->prev->next = cur->next;
2267: cur->next = cur->prev = NULL;
2268: cur->parent = NULL;
2269: }
2270:
1.78 daniel 2271: /**
2272: * xmlReplaceNode:
2273: * @old: the old node
2274: * @cur: the node
2275: *
2276: * Unlink the old node from it's current context, prune the new one
2277: * at the same place. If cur was already inserted in a document it is
2278: * first unlinked from its existing context.
2279: *
2280: * Returns the old node
2281: */
2282: xmlNodePtr
2283: xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) {
2284: if (old == NULL) {
1.86 daniel 2285: #ifdef DEBUG_TREE
1.78 daniel 2286: fprintf(stderr, "xmlReplaceNode : old == NULL\n");
1.86 daniel 2287: #endif
1.78 daniel 2288: return(NULL);
2289: }
2290: if (cur == NULL) {
2291: xmlUnlinkNode(old);
2292: return(old);
2293: }
2294: xmlUnlinkNode(cur);
2295: cur->doc = old->doc;
2296: cur->parent = old->parent;
2297: cur->next = old->next;
2298: if (cur->next != NULL)
2299: cur->next->prev = cur;
2300: cur->prev = old->prev;
2301: if (cur->prev != NULL)
2302: cur->prev->next = cur;
2303: if (cur->parent != NULL) {
1.90 daniel 2304: if (cur->parent->children == old)
2305: cur->parent->children = cur;
1.78 daniel 2306: if (cur->parent->last == old)
2307: cur->parent->last = cur;
2308: }
2309: old->next = old->prev = NULL;
2310: old->parent = NULL;
2311: return(old);
2312: }
2313:
1.1 veillard 2314: /************************************************************************
2315: * *
1.31 daniel 2316: * Copy operations *
2317: * *
2318: ************************************************************************/
2319:
2320: /**
2321: * xmlCopyNamespace:
2322: * @cur: the namespace
2323: *
2324: * Do a copy of the namespace.
2325: *
2326: * Returns: a new xmlNsPtr, or NULL in case of error.
2327: */
2328: xmlNsPtr
2329: xmlCopyNamespace(xmlNsPtr cur) {
2330: xmlNsPtr ret;
2331:
2332: if (cur == NULL) return(NULL);
2333: switch (cur->type) {
2334: case XML_GLOBAL_NAMESPACE:
2335: ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
2336: break;
2337: case XML_LOCAL_NAMESPACE:
2338: ret = xmlNewNs(NULL, cur->href, cur->prefix);
2339: break;
2340: default:
1.86 daniel 2341: #ifdef DEBUG_TREE
1.31 daniel 2342: fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1.86 daniel 2343: #endif
1.31 daniel 2344: return(NULL);
2345: }
2346: return(ret);
2347: }
2348:
2349: /**
2350: * xmlCopyNamespaceList:
2351: * @cur: the first namespace
2352: *
2353: * Do a copy of an namespace list.
2354: *
2355: * Returns: a new xmlNsPtr, or NULL in case of error.
2356: */
2357: xmlNsPtr
2358: xmlCopyNamespaceList(xmlNsPtr cur) {
2359: xmlNsPtr ret = NULL;
2360: xmlNsPtr p = NULL,q;
2361:
2362: while (cur != NULL) {
2363: q = xmlCopyNamespace(cur);
2364: if (p == NULL) {
2365: ret = p = q;
2366: } else {
2367: p->next = q;
2368: p = q;
2369: }
2370: cur = cur->next;
2371: }
2372: return(ret);
2373: }
2374:
2375: /**
2376: * xmlCopyProp:
1.56 daniel 2377: * @target: the element where the attribute will be grafted
1.31 daniel 2378: * @cur: the attribute
2379: *
2380: * Do a copy of the attribute.
2381: *
2382: * Returns: a new xmlAttrPtr, or NULL in case of error.
2383: */
2384: xmlAttrPtr
1.56 daniel 2385: xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
1.31 daniel 2386: xmlAttrPtr ret;
2387:
2388: if (cur == NULL) return(NULL);
1.94 daniel 2389: if (cur->parent != NULL)
2390: ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL);
2391: else if (cur->children != NULL)
1.90 daniel 2392: ret = xmlNewDocProp(cur->children->doc, cur->name, NULL);
1.31 daniel 2393: else
2394: ret = xmlNewDocProp(NULL, cur->name, NULL);
2395: if (ret == NULL) return(NULL);
1.94 daniel 2396: ret->parent = target;
1.56 daniel 2397:
2398: if ((cur->ns != NULL) && (target != NULL)) {
2399: xmlNsPtr ns;
2400:
2401: ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
2402: ret->ns = ns;
2403: } else
2404: ret->ns = NULL;
2405:
1.90 daniel 2406: if (cur->children != NULL)
2407: ret->children = xmlCopyNodeList(cur->children);
1.31 daniel 2408: return(ret);
2409: }
2410:
2411: /**
2412: * xmlCopyPropList:
1.56 daniel 2413: * @target: the element where the attributes will be grafted
1.31 daniel 2414: * @cur: the first attribute
2415: *
2416: * Do a copy of an attribute list.
2417: *
2418: * Returns: a new xmlAttrPtr, or NULL in case of error.
2419: */
2420: xmlAttrPtr
1.56 daniel 2421: xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
1.31 daniel 2422: xmlAttrPtr ret = NULL;
2423: xmlAttrPtr p = NULL,q;
2424:
2425: while (cur != NULL) {
1.56 daniel 2426: q = xmlCopyProp(target, cur);
1.31 daniel 2427: if (p == NULL) {
2428: ret = p = q;
2429: } else {
2430: p->next = q;
1.94 daniel 2431: q->prev = p;
1.31 daniel 2432: p = q;
2433: }
2434: cur = cur->next;
2435: }
2436: return(ret);
2437: }
2438:
2439: /*
1.68 daniel 2440: * NOTE abeut the CopyNode operations !
1.31 daniel 2441: *
2442: * They are splitted into external and internal parts for one
2443: * tricky reason: namespaces. Doing a direct copy of a node
2444: * say RPM:Copyright without changing the namespace pointer to
2445: * something else can produce stale links. One way to do it is
2446: * to keep a reference counter but this doesn't work as soon
2447: * as one move the element or the subtree out of the scope of
2448: * the existing namespace. The actual solution seems to add
2449: * a copy of the namespace at the top of the copied tree if
2450: * not available in the subtree.
2451: * Hence two functions, the public front-end call the inner ones
2452: */
2453:
2454: static xmlNodePtr
2455: xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
2456:
2457: static xmlNodePtr
2458: xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
2459: int recursive) {
2460: xmlNodePtr ret;
2461:
2462: if (node == NULL) return(NULL);
2463: /*
2464: * Allocate a new node and fill the fields.
2465: */
1.57 daniel 2466: ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.31 daniel 2467: if (ret == NULL) {
2468: fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
2469: return(NULL);
2470: }
1.90 daniel 2471: memset(ret, 0, sizeof(xmlNode));
2472: ret->type = node->type;
1.31 daniel 2473:
2474: ret->doc = doc;
2475: ret->parent = parent;
2476: if (node->name != NULL)
2477: ret->name = xmlStrdup(node->name);
1.70 daniel 2478: if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
2479: #ifndef XML_USE_BUFFER_CONTENT
1.31 daniel 2480: ret->content = xmlStrdup(node->content);
1.70 daniel 2481: #else
2482: ret->content = xmlBufferCreateSize(xmlBufferLength(node->content));
2483: xmlBufferSetAllocationScheme(ret->content,
2484: xmlGetBufferAllocationScheme());
2485: xmlBufferAdd(ret->content,
2486: xmlBufferContent(node->content),
2487: xmlBufferLength(node->content));
2488: #endif
1.90 daniel 2489: }
1.31 daniel 2490: if (parent != NULL)
2491: xmlAddChild(parent, ret);
2492:
2493: if (!recursive) return(ret);
2494: if (node->nsDef != NULL)
2495: ret->nsDef = xmlCopyNamespaceList(node->nsDef);
2496:
2497: if (node->ns != NULL) {
2498: xmlNsPtr ns;
2499:
2500: ns = xmlSearchNs(doc, ret, node->ns->prefix);
2501: if (ns == NULL) {
2502: /*
2503: * Humm, we are copying an element whose namespace is defined
2504: * out of the new tree scope. Search it in the original tree
2505: * and add it at the top of the new tree
2506: */
2507: ns = xmlSearchNs(node->doc, node, node->ns->prefix);
2508: if (ns != NULL) {
2509: xmlNodePtr root = ret;
2510:
2511: while (root->parent != NULL) root = root->parent;
2512: xmlNewNs(root, ns->href, ns->prefix);
2513: }
2514: } else {
2515: /*
2516: * reference the existing namespace definition in our own tree.
2517: */
2518: ret->ns = ns;
2519: }
2520: }
1.56 daniel 2521: if (node->properties != NULL)
2522: ret->properties = xmlCopyPropList(ret, node->properties);
1.90 daniel 2523: if (node->children != NULL)
2524: ret->children = xmlStaticCopyNodeList(node->children, doc, ret);
1.34 daniel 2525: UPDATE_LAST_CHILD(ret)
1.31 daniel 2526: return(ret);
2527: }
2528:
2529: static xmlNodePtr
2530: xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
2531: xmlNodePtr ret = NULL;
2532: xmlNodePtr p = NULL,q;
2533:
2534: while (node != NULL) {
2535: q = xmlStaticCopyNode(node, doc, parent, 1);
1.103 daniel 2536: if (ret == NULL) {
2537: q->prev = NULL;
2538: ret = p = q;
1.31 daniel 2539: } else {
1.103 daniel 2540: p->next = q;
2541: q->prev = p;
2542: p = q;
1.31 daniel 2543: }
2544: node = node->next;
2545: }
2546: return(ret);
2547: }
2548:
2549: /**
2550: * xmlCopyNode:
2551: * @node: the node
2552: * @recursive: if 1 do a recursive copy.
2553: *
2554: * Do a copy of the node.
2555: *
2556: * Returns: a new xmlNodePtr, or NULL in case of error.
2557: */
2558: xmlNodePtr
2559: xmlCopyNode(xmlNodePtr node, int recursive) {
2560: xmlNodePtr ret;
2561:
2562: ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
2563: return(ret);
2564: }
2565:
2566: /**
2567: * xmlCopyNodeList:
2568: * @node: the first node in the list.
2569: *
2570: * Do a recursive copy of the node list.
2571: *
2572: * Returns: a new xmlNodePtr, or NULL in case of error.
2573: */
2574: xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
2575: xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
2576: return(ret);
2577: }
2578:
2579: /**
2580: * xmlCopyElement:
2581: * @elem: the element
2582: *
2583: * Do a copy of the element definition.
2584: *
2585: * Returns: a new xmlElementPtr, or NULL in case of error.
2586: xmlElementPtr
2587: xmlCopyElement(xmlElementPtr elem) {
2588: xmlElementPtr ret;
2589:
2590: if (elem == NULL) return(NULL);
2591: ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
2592: if (ret == NULL) return(NULL);
2593: if (!recursive) return(ret);
2594: if (elem->properties != NULL)
2595: ret->properties = xmlCopyPropList(elem->properties);
2596:
2597: if (elem->nsDef != NULL)
2598: ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1.90 daniel 2599: if (elem->children != NULL)
2600: ret->children = xmlCopyElementList(elem->children);
1.31 daniel 2601: return(ret);
2602: }
2603: */
2604:
2605: /**
2606: * xmlCopyDtd:
2607: * @dtd: the dtd
2608: *
2609: * Do a copy of the dtd.
2610: *
2611: * Returns: a new xmlDtdPtr, or NULL in case of error.
2612: */
2613: xmlDtdPtr
2614: xmlCopyDtd(xmlDtdPtr dtd) {
2615: xmlDtdPtr ret;
2616:
2617: if (dtd == NULL) return(NULL);
2618: ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
2619: if (ret == NULL) return(NULL);
2620: if (dtd->entities != NULL)
2621: ret->entities = (void *) xmlCopyEntitiesTable(
2622: (xmlEntitiesTablePtr) dtd->entities);
1.35 daniel 2623: if (dtd->notations != NULL)
2624: ret->notations = (void *) xmlCopyNotationTable(
2625: (xmlNotationTablePtr) dtd->notations);
2626: if (dtd->elements != NULL)
2627: ret->elements = (void *) xmlCopyElementTable(
2628: (xmlElementTablePtr) dtd->elements);
2629: if (dtd->attributes != NULL)
2630: ret->attributes = (void *) xmlCopyAttributeTable(
2631: (xmlAttributeTablePtr) dtd->attributes);
1.31 daniel 2632: return(ret);
2633: }
2634:
2635: /**
2636: * xmlCopyDoc:
2637: * @doc: the document
2638: * @recursive: if 1 do a recursive copy.
2639: *
2640: * Do a copy of the document info. If recursive, the content tree will
2641: * be copied too as well as Dtd, namespaces and entities.
2642: *
2643: * Returns: a new xmlDocPtr, or NULL in case of error.
2644: */
2645: xmlDocPtr
2646: xmlCopyDoc(xmlDocPtr doc, int recursive) {
2647: xmlDocPtr ret;
2648:
2649: if (doc == NULL) return(NULL);
2650: ret = xmlNewDoc(doc->version);
2651: if (ret == NULL) return(NULL);
2652: if (doc->name != NULL)
1.57 daniel 2653: ret->name = xmlMemStrdup(doc->name);
1.31 daniel 2654: if (doc->encoding != NULL)
2655: ret->encoding = xmlStrdup(doc->encoding);
2656: ret->compression = doc->compression;
2657: ret->standalone = doc->standalone;
2658: if (!recursive) return(ret);
2659:
2660: if (doc->intSubset != NULL)
2661: ret->intSubset = xmlCopyDtd(doc->intSubset);
2662: if (doc->oldNs != NULL)
2663: ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
1.90 daniel 2664: if (doc->children != NULL)
1.103 daniel 2665: ret->children = xmlStaticCopyNodeList(doc->children, ret,
2666: (xmlNodePtr)ret);
1.31 daniel 2667: return(ret);
2668: }
2669:
2670: /************************************************************************
2671: * *
1.1 veillard 2672: * Content access functions *
2673: * *
2674: ************************************************************************/
2675:
1.23 daniel 2676: /**
1.75 daniel 2677: * xmlDocGetRootElement:
2678: * @doc: the document
2679: *
1.90 daniel 2680: * Get the root element of the document (doc->children is a list
1.75 daniel 2681: * containing possibly comments, PIs, etc ...).
2682: *
2683: * Returns the xmlNodePtr for the root or NULL
2684: */
2685: xmlNodePtr
2686: xmlDocGetRootElement(xmlDocPtr doc) {
2687: xmlNodePtr ret;
2688:
2689: if (doc == NULL) return(NULL);
1.90 daniel 2690: ret = doc->children;
1.75 daniel 2691: while (ret != NULL) {
2692: if (ret->type == XML_ELEMENT_NODE)
2693: return(ret);
2694: ret = ret->next;
2695: }
2696: return(ret);
2697: }
2698:
2699: /**
1.78 daniel 2700: * xmlDocSetRootElement:
2701: * @doc: the document
2702: * @root: the new document root element
2703: *
1.90 daniel 2704: * Set the root element of the document (doc->children is a list
1.78 daniel 2705: * containing possibly comments, PIs, etc ...).
2706: *
2707: * Returns the old root element if any was found
2708: */
2709: xmlNodePtr
2710: xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) {
2711: xmlNodePtr old = NULL;
2712:
2713: if (doc == NULL) return(NULL);
1.90 daniel 2714: old = doc->children;
1.78 daniel 2715: while (old != NULL) {
2716: if (old->type == XML_ELEMENT_NODE)
2717: break;
2718: old = old->next;
2719: }
2720: if (old == NULL) {
1.90 daniel 2721: if (doc->children == NULL) {
2722: doc->children = root;
1.78 daniel 2723: } else {
1.90 daniel 2724: xmlAddSibling(doc->children, root);
1.78 daniel 2725: }
2726: } else {
2727: xmlReplaceNode(old, root);
2728: }
2729: return(old);
2730: }
2731:
2732: /**
1.52 daniel 2733: * xmlNodeSetLang:
2734: * @cur: the node being changed
2735: * @lang: the langage description
2736: *
1.78 daniel 2737: * Set the language of a node, i.e. the values of the xml:lang
2738: * attribute.
1.52 daniel 2739: */
2740: void
1.61 daniel 2741: xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) {
1.78 daniel 2742: if (cur == NULL) return;
2743: switch(cur->type) {
2744: case XML_TEXT_NODE:
2745: case XML_CDATA_SECTION_NODE:
2746: case XML_COMMENT_NODE:
2747: case XML_DOCUMENT_NODE:
2748: case XML_DOCUMENT_TYPE_NODE:
2749: case XML_DOCUMENT_FRAG_NODE:
2750: case XML_NOTATION_NODE:
2751: case XML_HTML_DOCUMENT_NODE:
1.90 daniel 2752: case XML_DTD_NODE:
1.91 daniel 2753: case XML_ELEMENT_DECL:
2754: case XML_ATTRIBUTE_DECL:
1.96 daniel 2755: case XML_ENTITY_DECL:
1.121 veillard 2756: case XML_PI_NODE:
2757: case XML_ENTITY_REF_NODE:
2758: case XML_ENTITY_NODE:
1.123 veillard 2759: #ifdef LIBXML_SGML_ENABLED
2760: case XML_SGML_DOCUMENT_NODE:
2761: #endif
1.78 daniel 2762: return;
2763: case XML_ELEMENT_NODE:
2764: case XML_ATTRIBUTE_NODE:
2765: break;
2766: }
1.54 daniel 2767: xmlSetProp(cur, BAD_CAST "xml:lang", lang);
1.52 daniel 2768: }
2769:
2770: /**
2771: * xmlNodeGetLang:
2772: * @cur: the node being checked
2773: *
2774: * Searches the language of a node, i.e. the values of the xml:lang
2775: * attribute or the one carried by the nearest ancestor.
2776: *
2777: * Returns a pointer to the lang value, or NULL if not found
1.69 daniel 2778: * It's up to the caller to free the memory.
1.52 daniel 2779: */
1.69 daniel 2780: xmlChar *
1.52 daniel 2781: xmlNodeGetLang(xmlNodePtr cur) {
1.69 daniel 2782: xmlChar *lang;
1.52 daniel 2783:
2784: while (cur != NULL) {
1.54 daniel 2785: lang = xmlGetProp(cur, BAD_CAST "xml:lang");
1.52 daniel 2786: if (lang != NULL)
2787: return(lang);
2788: cur = cur->parent;
2789: }
2790: return(NULL);
1.78 daniel 2791: }
2792:
1.133 ! veillard 2793:
! 2794: /**
! 2795: * xmlNodeSetSpacePreserve:
! 2796: * @cur: the node being changed
! 2797: * @val: the xml:space value ("0": default, 1: "preserve")
! 2798: *
! 2799: * Set (or reset) the space preserving behaviour of a node, i.e. the
! 2800: * value of the xml:space attribute.
! 2801: */
! 2802: void
! 2803: xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) {
! 2804: if (cur == NULL) return;
! 2805: switch(cur->type) {
! 2806: case XML_TEXT_NODE:
! 2807: case XML_CDATA_SECTION_NODE:
! 2808: case XML_COMMENT_NODE:
! 2809: case XML_DOCUMENT_NODE:
! 2810: case XML_DOCUMENT_TYPE_NODE:
! 2811: case XML_DOCUMENT_FRAG_NODE:
! 2812: case XML_NOTATION_NODE:
! 2813: case XML_HTML_DOCUMENT_NODE:
! 2814: case XML_DTD_NODE:
! 2815: case XML_ELEMENT_DECL:
! 2816: case XML_ATTRIBUTE_DECL:
! 2817: case XML_ENTITY_DECL:
! 2818: case XML_PI_NODE:
! 2819: case XML_ENTITY_REF_NODE:
! 2820: case XML_ENTITY_NODE:
! 2821: #ifdef LIBXML_SGML_ENABLED
! 2822: case XML_SGML_DOCUMENT_NODE:
! 2823: #endif
! 2824: return;
! 2825: case XML_ELEMENT_NODE:
! 2826: case XML_ATTRIBUTE_NODE:
! 2827: break;
! 2828: }
! 2829: switch (val) {
! 2830: case 0:
! 2831: xmlSetProp(cur, BAD_CAST "xml:space", BAD_CAST "default");
! 2832: break;
! 2833: case 1:
! 2834: xmlSetProp(cur, BAD_CAST "xml:space",
! 2835: BAD_CAST "preserve");
! 2836: break;
! 2837: }
! 2838: }
! 2839:
1.78 daniel 2840: /**
1.98 daniel 2841: * xmlNodeGetSpacePreserve:
2842: * @cur: the node being checked
2843: *
1.133 ! veillard 2844: * Searches the space preserving behaviour of a node, i.e. the values
! 2845: * of the xml:space attribute or the one carried by the nearest
! 2846: * ancestor.
1.98 daniel 2847: *
2848: * Returns -1 if xml:space is not inheried, 0 if "default", 1 if "preserve"
2849: */
2850: int
2851: xmlNodeGetSpacePreserve(xmlNodePtr cur) {
2852: xmlChar *space;
2853:
2854: while (cur != NULL) {
2855: space = xmlGetProp(cur, BAD_CAST "xml:space");
2856: if (space != NULL) {
1.128 veillard 2857: if (xmlStrEqual(space, BAD_CAST "preserve")) {
1.98 daniel 2858: xmlFree(space);
2859: return(1);
2860: }
1.128 veillard 2861: if (xmlStrEqual(space, BAD_CAST "default")) {
1.98 daniel 2862: xmlFree(space);
2863: return(0);
2864: }
2865: xmlFree(space);
2866: }
2867: cur = cur->parent;
2868: }
2869: return(-1);
2870: }
2871:
2872: /**
1.78 daniel 2873: * xmlNodeSetName:
2874: * @cur: the node being changed
2875: * @name: the new tag name
2876: *
1.133 ! veillard 2877: * Set (or reset) the name of a node.
1.78 daniel 2878: */
2879: void
2880: xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) {
2881: if (cur == NULL) return;
2882: if (name == NULL) return;
2883: switch(cur->type) {
2884: case XML_TEXT_NODE:
2885: case XML_CDATA_SECTION_NODE:
2886: case XML_COMMENT_NODE:
2887: case XML_DOCUMENT_TYPE_NODE:
2888: case XML_DOCUMENT_FRAG_NODE:
2889: case XML_NOTATION_NODE:
2890: case XML_HTML_DOCUMENT_NODE:
1.123 veillard 2891: #ifdef LIBXML_SGML_ENABLED
2892: case XML_SGML_DOCUMENT_NODE:
2893: #endif
1.78 daniel 2894: return;
2895: case XML_ELEMENT_NODE:
2896: case XML_ATTRIBUTE_NODE:
2897: case XML_PI_NODE:
2898: case XML_ENTITY_REF_NODE:
2899: case XML_ENTITY_NODE:
1.90 daniel 2900: case XML_DTD_NODE:
2901: case XML_DOCUMENT_NODE:
1.96 daniel 2902: case XML_ELEMENT_DECL:
2903: case XML_ATTRIBUTE_DECL:
2904: case XML_ENTITY_DECL:
1.78 daniel 2905: break;
2906: }
2907: if (cur->name != NULL) xmlFree((xmlChar *) cur->name);
2908: cur->name = xmlStrdup(name);
1.52 daniel 2909: }
2910:
1.133 ! veillard 2911: /**
! 2912: * xmlNodeSetBase:
! 2913: * @cur: the node being changed
! 2914: * @uri: the new base URI
! 2915: *
! 2916: * Set (or reset) the base URI of a node, i.e. the value of the
! 2917: * xml:base attribute.
! 2918: */
! 2919: void
! 2920: xmlNodeSetBase(xmlNodePtr cur, xmlChar* uri) {
! 2921: if (cur == NULL) return;
! 2922: switch(cur->type) {
! 2923: case XML_TEXT_NODE:
! 2924: case XML_CDATA_SECTION_NODE:
! 2925: case XML_COMMENT_NODE:
! 2926: case XML_DOCUMENT_NODE:
! 2927: case XML_DOCUMENT_TYPE_NODE:
! 2928: case XML_DOCUMENT_FRAG_NODE:
! 2929: case XML_NOTATION_NODE:
! 2930: case XML_HTML_DOCUMENT_NODE:
! 2931: case XML_DTD_NODE:
! 2932: case XML_ELEMENT_DECL:
! 2933: case XML_ATTRIBUTE_DECL:
! 2934: case XML_ENTITY_DECL:
! 2935: case XML_PI_NODE:
! 2936: case XML_ENTITY_REF_NODE:
! 2937: case XML_ENTITY_NODE:
! 2938: #ifdef LIBXML_SGML_ENABLED
! 2939: case XML_SGML_DOCUMENT_NODE:
! 2940: #endif
! 2941: return;
! 2942: case XML_ELEMENT_NODE:
! 2943: case XML_ATTRIBUTE_NODE:
! 2944: break;
! 2945: }
! 2946: xmlSetProp(cur, BAD_CAST "xml:base", uri);
! 2947: }
! 2948:
1.52 daniel 2949: /**
1.73 daniel 2950: * xmlNodeGetBase:
2951: * @doc: the document the node pertains to
2952: * @cur: the node being checked
2953: *
2954: * Searches for the BASE URL. The code should work on both XML
2955: * and HTML document even if base mechanisms are completely different.
2956: *
2957: * Returns a pointer to the base URL, or NULL if not found
2958: * It's up to the caller to free the memory.
2959: */
2960: xmlChar *
2961: xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) {
2962: xmlChar *base;
2963:
2964: if ((cur == NULL) && (doc == NULL))
2965: return(NULL);
2966: if (doc == NULL) doc = cur->doc;
2967: if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
1.90 daniel 2968: cur = doc->children;
1.73 daniel 2969: while ((cur != NULL) && (cur->name != NULL)) {
1.122 veillard 2970: if (cur->type == XML_ENTITY_DECL) {
2971: /* TODO: we are crossing entity boundaries */
2972: }
1.73 daniel 2973: if (cur->type != XML_ELEMENT_NODE) {
2974: cur = cur->next;
2975: continue;
2976: }
1.126 veillard 2977: if (!xmlStrcasecmp(cur->name, BAD_CAST "html")) {
1.90 daniel 2978: cur = cur->children;
1.73 daniel 2979: continue;
2980: }
1.126 veillard 2981: if (!xmlStrcasecmp(cur->name, BAD_CAST "head")) {
1.90 daniel 2982: cur = cur->children;
1.73 daniel 2983: continue;
2984: }
1.126 veillard 2985: if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) {
2986: return(xmlGetProp(cur, BAD_CAST "href"));
1.73 daniel 2987: }
1.100 daniel 2988: cur = cur->next;
1.73 daniel 2989: }
1.100 daniel 2990: if ((doc != NULL) && (doc->URL != NULL))
2991: return(xmlStrdup(doc->URL));
1.73 daniel 2992: return(NULL);
2993: }
2994: while (cur != NULL) {
2995: base = xmlGetProp(cur, BAD_CAST "xml:base");
2996: if (base != NULL)
2997: return(base);
2998: cur = cur->parent;
2999: }
1.100 daniel 3000: if ((doc != NULL) && (doc->URL != NULL))
3001: return(xmlStrdup(doc->URL));
1.73 daniel 3002: return(NULL);
3003: }
3004:
3005: /**
1.28 daniel 3006: * xmlNodeGetContent:
3007: * @cur: the node being read
3008: *
3009: * Read the value of a node, this can be either the text carried
3010: * directly by this node if it's a TEXT node or the aggregate string
3011: * of the values carried by this node child's (TEXT and ENTITY_REF).
3012: * Entity references are substitued.
1.61 daniel 3013: * Returns a new xmlChar * or NULL if no content is available.
1.38 daniel 3014: * It's up to the caller to free the memory.
1.28 daniel 3015: */
1.61 daniel 3016: xmlChar *
1.28 daniel 3017: xmlNodeGetContent(xmlNodePtr cur) {
3018: if (cur == NULL) return(NULL);
3019: switch (cur->type) {
3020: case XML_DOCUMENT_FRAG_NODE:
3021: case XML_ELEMENT_NODE:
1.90 daniel 3022: return(xmlNodeListGetString(cur->doc, cur->children, 1));
1.28 daniel 3023: break;
1.52 daniel 3024: case XML_ATTRIBUTE_NODE: {
3025: xmlAttrPtr attr = (xmlAttrPtr) cur;
1.90 daniel 3026: if (attr->parent != NULL)
3027: return(xmlNodeListGetString(attr->parent->doc, attr->children, 1));
1.52 daniel 3028: else
1.90 daniel 3029: return(xmlNodeListGetString(NULL, attr->children, 1));
1.52 daniel 3030: break;
3031: }
1.82 daniel 3032: case XML_COMMENT_NODE:
1.52 daniel 3033: case XML_PI_NODE:
3034: if (cur->content != NULL)
1.70 daniel 3035: #ifndef XML_USE_BUFFER_CONTENT
1.52 daniel 3036: return(xmlStrdup(cur->content));
1.70 daniel 3037: #else
3038: return(xmlStrdup(xmlBufferContent(cur->content)));
3039: #endif
1.52 daniel 3040: return(NULL);
1.28 daniel 3041: case XML_ENTITY_REF_NODE:
1.82 daniel 3042: /*
3043: * Locate the entity, and get it's content
3044: * @@@
3045: */
3046: return(NULL);
1.28 daniel 3047: case XML_ENTITY_NODE:
3048: case XML_DOCUMENT_NODE:
1.65 daniel 3049: case XML_HTML_DOCUMENT_NODE:
1.28 daniel 3050: case XML_DOCUMENT_TYPE_NODE:
3051: case XML_NOTATION_NODE:
1.90 daniel 3052: case XML_DTD_NODE:
1.123 veillard 3053: #ifdef LIBXML_SGML_ENABLED
3054: case XML_SGML_DOCUMENT_NODE:
3055: #endif
1.28 daniel 3056: return(NULL);
1.91 daniel 3057: case XML_ELEMENT_DECL:
3058: /* TODO !!! */
3059: return(NULL);
3060: case XML_ATTRIBUTE_DECL:
3061: /* TODO !!! */
3062: return(NULL);
1.96 daniel 3063: case XML_ENTITY_DECL:
3064: /* TODO !!! */
3065: return(NULL);
1.50 daniel 3066: case XML_CDATA_SECTION_NODE:
1.28 daniel 3067: case XML_TEXT_NODE:
3068: if (cur->content != NULL)
1.70 daniel 3069: #ifndef XML_USE_BUFFER_CONTENT
1.28 daniel 3070: return(xmlStrdup(cur->content));
1.70 daniel 3071: #else
3072: return(xmlStrdup(xmlBufferContent(cur->content)));
3073: #endif
1.28 daniel 3074: return(NULL);
3075: }
3076: return(NULL);
3077: }
3078:
3079: /**
1.23 daniel 3080: * xmlNodeSetContent:
3081: * @cur: the node being modified
3082: * @content: the new value of the content
3083: *
3084: * Replace the content of a node.
1.1 veillard 3085: */
1.28 daniel 3086: void
1.61 daniel 3087: xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) {
1.1 veillard 3088: if (cur == NULL) {
1.86 daniel 3089: #ifdef DEBUG_TREE
1.1 veillard 3090: fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
1.86 daniel 3091: #endif
1.1 veillard 3092: return;
3093: }
1.28 daniel 3094: switch (cur->type) {
3095: case XML_DOCUMENT_FRAG_NODE:
3096: case XML_ELEMENT_NODE:
3097: if (cur->content != NULL) {
1.70 daniel 3098: #ifndef XML_USE_BUFFER_CONTENT
1.57 daniel 3099: xmlFree(cur->content);
1.70 daniel 3100: #else
3101: xmlBufferFree(cur->content);
3102: #endif
1.28 daniel 3103: cur->content = NULL;
3104: }
1.90 daniel 3105: if (cur->children != NULL) xmlFreeNodeList(cur->children);
3106: cur->children = xmlStringGetNodeList(cur->doc, content);
1.34 daniel 3107: UPDATE_LAST_CHILD(cur)
1.28 daniel 3108: break;
3109: case XML_ATTRIBUTE_NODE:
3110: break;
3111: case XML_TEXT_NODE:
3112: case XML_CDATA_SECTION_NODE:
3113: case XML_ENTITY_REF_NODE:
3114: case XML_ENTITY_NODE:
3115: case XML_PI_NODE:
3116: case XML_COMMENT_NODE:
1.70 daniel 3117: if (cur->content != NULL) {
3118: #ifndef XML_USE_BUFFER_CONTENT
3119: xmlFree(cur->content);
3120: #else
3121: xmlBufferFree(cur->content);
3122: #endif
3123: }
1.90 daniel 3124: if (cur->children != NULL) xmlFreeNodeList(cur->children);
3125: cur->last = cur->children = NULL;
1.70 daniel 3126: if (content != NULL) {
3127: #ifndef XML_USE_BUFFER_CONTENT
1.28 daniel 3128: cur->content = xmlStrdup(content);
1.70 daniel 3129: #else
3130: cur->content = xmlBufferCreateSize(0);
3131: xmlBufferSetAllocationScheme(cur->content,
3132: xmlGetBufferAllocationScheme());
3133: xmlBufferAdd(cur->content, content, -1);
3134: #endif
3135: } else
1.28 daniel 3136: cur->content = NULL;
1.53 daniel 3137: break;
1.28 daniel 3138: case XML_DOCUMENT_NODE:
1.65 daniel 3139: case XML_HTML_DOCUMENT_NODE:
1.28 daniel 3140: case XML_DOCUMENT_TYPE_NODE:
1.123 veillard 3141: #ifdef LIBXML_SGML_ENABLED
3142: case XML_SGML_DOCUMENT_NODE:
3143: #endif
1.28 daniel 3144: break;
3145: case XML_NOTATION_NODE:
3146: break;
1.90 daniel 3147: case XML_DTD_NODE:
3148: break;
1.91 daniel 3149: case XML_ELEMENT_DECL:
3150: /* TODO !!! */
3151: break;
3152: case XML_ATTRIBUTE_DECL:
3153: /* TODO !!! */
3154: break;
1.96 daniel 3155: case XML_ENTITY_DECL:
3156: /* TODO !!! */
3157: break;
1.28 daniel 3158: }
1.1 veillard 3159: }
3160:
1.23 daniel 3161: /**
3162: * xmlNodeSetContentLen:
3163: * @cur: the node being modified
3164: * @content: the new value of the content
3165: * @len: the size of @content
3166: *
3167: * Replace the content of a node.
1.21 daniel 3168: */
1.28 daniel 3169: void
1.61 daniel 3170: xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
1.21 daniel 3171: if (cur == NULL) {
1.86 daniel 3172: #ifdef DEBUG_TREE
1.28 daniel 3173: fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
1.86 daniel 3174: #endif
1.21 daniel 3175: return;
3176: }
1.28 daniel 3177: switch (cur->type) {
3178: case XML_DOCUMENT_FRAG_NODE:
3179: case XML_ELEMENT_NODE:
3180: if (cur->content != NULL) {
1.70 daniel 3181: #ifndef XML_USE_BUFFER_CONTENT
1.57 daniel 3182: xmlFree(cur->content);
1.70 daniel 3183: #else
3184: xmlBufferFree(cur->content);
3185: #endif
1.28 daniel 3186: cur->content = NULL;
3187: }
1.90 daniel 3188: if (cur->children != NULL) xmlFreeNodeList(cur->children);
3189: cur->children = xmlStringLenGetNodeList(cur->doc, content, len);
1.34 daniel 3190: UPDATE_LAST_CHILD(cur)
1.28 daniel 3191: break;
3192: case XML_ATTRIBUTE_NODE:
3193: break;
3194: case XML_TEXT_NODE:
3195: case XML_CDATA_SECTION_NODE:
3196: case XML_ENTITY_REF_NODE:
3197: case XML_ENTITY_NODE:
3198: case XML_PI_NODE:
3199: case XML_COMMENT_NODE:
1.70 daniel 3200: case XML_NOTATION_NODE:
3201: if (cur->content != NULL) {
3202: #ifndef XML_USE_BUFFER_CONTENT
3203: xmlFree(cur->content);
3204: #else
3205: xmlBufferFree(cur->content);
3206: #endif
3207: }
1.90 daniel 3208: if (cur->children != NULL) xmlFreeNodeList(cur->children);
3209: cur->children = cur->last = NULL;
1.70 daniel 3210: if (content != NULL) {
3211: #ifndef XML_USE_BUFFER_CONTENT
1.28 daniel 3212: cur->content = xmlStrndup(content, len);
1.70 daniel 3213: #else
3214: cur->content = xmlBufferCreateSize(len);
3215: xmlBufferSetAllocationScheme(cur->content,
3216: xmlGetBufferAllocationScheme());
3217: xmlBufferAdd(cur->content, content, len);
3218: #endif
3219: } else
1.28 daniel 3220: cur->content = NULL;
1.53 daniel 3221: break;
1.28 daniel 3222: case XML_DOCUMENT_NODE:
1.90 daniel 3223: case XML_DTD_NODE:
1.65 daniel 3224: case XML_HTML_DOCUMENT_NODE:
1.28 daniel 3225: case XML_DOCUMENT_TYPE_NODE:
1.123 veillard 3226: #ifdef LIBXML_SGML_ENABLED
3227: case XML_SGML_DOCUMENT_NODE:
3228: #endif
1.28 daniel 3229: break;
1.91 daniel 3230: case XML_ELEMENT_DECL:
3231: /* TODO !!! */
3232: break;
3233: case XML_ATTRIBUTE_DECL:
3234: /* TODO !!! */
3235: break;
1.96 daniel 3236: case XML_ENTITY_DECL:
3237: /* TODO !!! */
3238: break;
1.28 daniel 3239: }
1.21 daniel 3240: }
3241:
1.23 daniel 3242: /**
1.28 daniel 3243: * xmlNodeAddContentLen:
1.23 daniel 3244: * @cur: the node being modified
3245: * @content: extra content
1.28 daniel 3246: * @len: the size of @content
1.23 daniel 3247: *
3248: * Append the extra substring to the node content.
1.21 daniel 3249: */
1.28 daniel 3250: void
1.61 daniel 3251: xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) {
1.21 daniel 3252: if (cur == NULL) {
1.86 daniel 3253: #ifdef DEBUG_TREE
1.28 daniel 3254: fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
1.86 daniel 3255: #endif
1.21 daniel 3256: return;
3257: }
1.28 daniel 3258: if (len <= 0) return;
3259: switch (cur->type) {
3260: case XML_DOCUMENT_FRAG_NODE:
3261: case XML_ELEMENT_NODE: {
1.112 veillard 3262: xmlNodePtr last = NULL, newNode;
1.28 daniel 3263:
1.90 daniel 3264: if (cur->children != NULL) {
1.32 daniel 3265: last = cur->last;
1.28 daniel 3266: } else {
3267: if (cur->content != NULL) {
1.70 daniel 3268: #ifndef XML_USE_BUFFER_CONTENT
1.90 daniel 3269: cur->children = xmlStringGetNodeList(cur->doc, cur->content);
1.70 daniel 3270: #else
1.90 daniel 3271: cur->children = xmlStringGetNodeList(cur->doc,
1.70 daniel 3272: xmlBufferContent(cur->content));
3273: #endif
1.34 daniel 3274: UPDATE_LAST_CHILD(cur)
1.70 daniel 3275: #ifndef XML_USE_BUFFER_CONTENT
1.57 daniel 3276: xmlFree(cur->content);
1.70 daniel 3277: #else
3278: xmlBufferFree(cur->content);
3279: #endif
1.28 daniel 3280: cur->content = NULL;
1.32 daniel 3281: last = cur->last;
1.28 daniel 3282: }
3283: }
1.112 veillard 3284: newNode = xmlNewTextLen(content, len);
3285: if (newNode != NULL) {
3286: xmlAddChild(cur, newNode);
3287: if ((last != NULL) && (last->next == newNode)) {
3288: xmlTextMerge(last, newNode);
1.32 daniel 3289: }
1.28 daniel 3290: }
3291: break;
3292: }
3293: case XML_ATTRIBUTE_NODE:
3294: break;
3295: case XML_TEXT_NODE:
3296: case XML_CDATA_SECTION_NODE:
3297: case XML_ENTITY_REF_NODE:
3298: case XML_ENTITY_NODE:
3299: case XML_PI_NODE:
3300: case XML_COMMENT_NODE:
1.70 daniel 3301: case XML_NOTATION_NODE:
3302: if (content != NULL) {
3303: #ifndef XML_USE_BUFFER_CONTENT
1.28 daniel 3304: cur->content = xmlStrncat(cur->content, content, len);
1.70 daniel 3305: #else
3306: xmlBufferAdd(cur->content, content, len);
3307: #endif
3308: }
1.28 daniel 3309: case XML_DOCUMENT_NODE:
1.90 daniel 3310: case XML_DTD_NODE:
1.65 daniel 3311: case XML_HTML_DOCUMENT_NODE:
1.28 daniel 3312: case XML_DOCUMENT_TYPE_NODE:
1.123 veillard 3313: #ifdef LIBXML_SGML_ENABLED
3314: case XML_SGML_DOCUMENT_NODE:
3315: #endif
1.28 daniel 3316: break;
1.91 daniel 3317: case XML_ELEMENT_DECL:
3318: case XML_ATTRIBUTE_DECL:
1.96 daniel 3319: case XML_ENTITY_DECL:
1.91 daniel 3320: break;
1.28 daniel 3321: }
1.21 daniel 3322: }
3323:
1.23 daniel 3324: /**
1.28 daniel 3325: * xmlNodeAddContent:
1.23 daniel 3326: * @cur: the node being modified
3327: * @content: extra content
3328: *
3329: * Append the extra substring to the node content.
1.21 daniel 3330: */
1.28 daniel 3331: void
1.61 daniel 3332: xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) {
1.28 daniel 3333: int len;
3334:
1.21 daniel 3335: if (cur == NULL) {
1.86 daniel 3336: #ifdef DEBUG_TREE
1.21 daniel 3337: fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
1.86 daniel 3338: #endif
1.21 daniel 3339: return;
3340: }
1.28 daniel 3341: if (content == NULL) return;
3342: len = xmlStrlen(content);
3343: xmlNodeAddContentLen(cur, content, len);
3344: }
3345:
3346: /**
3347: * xmlTextMerge:
3348: * @first: the first text node
3349: * @second: the second text node being merged
3350: *
3351: * Merge two text nodes into one
1.36 daniel 3352: * Returns the first text node augmented
1.28 daniel 3353: */
3354: xmlNodePtr
3355: xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
3356: if (first == NULL) return(second);
3357: if (second == NULL) return(first);
3358: if (first->type != XML_TEXT_NODE) return(first);
3359: if (second->type != XML_TEXT_NODE) return(first);
1.70 daniel 3360: #ifndef XML_USE_BUFFER_CONTENT
1.28 daniel 3361: xmlNodeAddContent(first, second->content);
1.70 daniel 3362: #else
3363: xmlNodeAddContent(first, xmlBufferContent(second->content));
3364: #endif
1.28 daniel 3365: xmlUnlinkNode(second);
3366: xmlFreeNode(second);
3367: return(first);
1.21 daniel 3368: }
3369:
1.23 daniel 3370: /**
1.52 daniel 3371: * xmlGetNsList:
3372: * @doc: the document
3373: * @node: the current node
3374: *
3375: * Search all the namespace applying to a given element.
3376: * Returns an NULL terminated array of all the xmlNsPtr found
3377: * that need to be freed by the caller or NULL if no
3378: * namespace if defined
3379: */
3380: xmlNsPtr *
3381: xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
3382: xmlNsPtr cur;
3383: xmlNsPtr *ret = NULL;
3384: int nbns = 0;
3385: int maxns = 10;
3386: int i;
3387:
3388: while (node != NULL) {
3389: cur = node->nsDef;
3390: while (cur != NULL) {
3391: if (ret == NULL) {
1.57 daniel 3392: ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
1.52 daniel 3393: if (ret == NULL) {
3394: fprintf(stderr, "xmlGetNsList : out of memory!\n");
3395: return(NULL);
3396: }
3397: ret[nbns] = NULL;
3398: }
3399: for (i = 0;i < nbns;i++) {
3400: if ((cur->prefix == ret[i]->prefix) ||
1.128 veillard 3401: (xmlStrEqual(cur->prefix, ret[i]->prefix))) break;
1.52 daniel 3402: }
3403: if (i >= nbns) {
3404: if (nbns >= maxns) {
3405: maxns *= 2;
1.57 daniel 3406: ret = (xmlNsPtr *) xmlRealloc(ret,
1.52 daniel 3407: (maxns + 1) * sizeof(xmlNsPtr));
3408: if (ret == NULL) {
3409: fprintf(stderr, "xmlGetNsList : realloc failed!\n");
3410: return(NULL);
3411: }
3412: }
3413: ret[nbns++] = cur;
3414: ret[nbns] = NULL;
3415: }
3416:
3417: cur = cur->next;
3418: }
3419: node = node->parent;
3420: }
3421: return(ret);
3422: }
3423:
3424: /**
1.23 daniel 3425: * xmlSearchNs:
3426: * @doc: the document
3427: * @node: the current node
3428: * @nameSpace: the namespace string
3429: *
1.16 daniel 3430: * Search a Ns registered under a given name space for a document.
1.23 daniel 3431: * recurse on the parents until it finds the defined namespace
3432: * or return NULL otherwise.
3433: * @nameSpace can be NULL, this is a search for the default namespace.
1.120 veillard 3434: * We don't allow to cross entities boundaries. If you don't declare
3435: * the namespace within those you will be in troubles !!! A warning
3436: * is generated to cover this case.
3437: *
1.36 daniel 3438: * Returns the namespace pointer or NULL.
1.3 veillard 3439: */
1.28 daniel 3440: xmlNsPtr
1.61 daniel 3441: xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) {
1.16 daniel 3442: xmlNsPtr cur;
1.3 veillard 3443:
1.76 daniel 3444: if (node == NULL) return(NULL);
1.19 daniel 3445: while (node != NULL) {
1.120 veillard 3446: if ((node->type == XML_ENTITY_REF_NODE) ||
3447: (node->type == XML_ENTITY_NODE) ||
3448: (node->type == XML_ENTITY_DECL))
3449: return(NULL);
1.92 daniel 3450: if (node->type == XML_ELEMENT_NODE) {
3451: cur = node->nsDef;
3452: while (cur != NULL) {
1.120 veillard 3453: if ((cur->prefix == NULL) && (nameSpace == NULL) &&
3454: (cur->href != NULL))
1.92 daniel 3455: return(cur);
3456: if ((cur->prefix != NULL) && (nameSpace != NULL) &&
1.120 veillard 3457: (cur->href != NULL) &&
1.128 veillard 3458: (xmlStrEqual(cur->prefix, nameSpace)))
1.92 daniel 3459: return(cur);
3460: cur = cur->next;
3461: }
1.19 daniel 3462: }
3463: node = node->parent;
3464: }
3465: return(NULL);
3466: }
1.3 veillard 3467:
1.23 daniel 3468: /**
3469: * xmlSearchNsByHref:
3470: * @doc: the document
3471: * @node: the current node
3472: * @href: the namespace value
3473: *
3474: * Search a Ns aliasing a given URI. Recurse on the parents until it finds
3475: * the defined namespace or return NULL otherwise.
1.36 daniel 3476: * Returns the namespace pointer or NULL.
1.19 daniel 3477: */
1.28 daniel 3478: xmlNsPtr
1.61 daniel 3479: xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) {
1.19 daniel 3480: xmlNsPtr cur;
1.82 daniel 3481: xmlNodePtr orig = node;
1.19 daniel 3482:
1.74 daniel 3483: if ((node == NULL) || (href == NULL)) return(NULL);
1.19 daniel 3484: while (node != NULL) {
3485: cur = node->nsDef;
3486: while (cur != NULL) {
3487: if ((cur->href != NULL) && (href != NULL) &&
1.128 veillard 3488: (xmlStrEqual(cur->href, href))) {
1.82 daniel 3489: /*
3490: * Check that the prefix is not shadowed between orig and node
3491: */
3492: xmlNodePtr check = orig;
3493: xmlNsPtr tst;
3494:
3495: while (check != node) {
3496: tst = check->nsDef;
3497: while (tst != NULL) {
3498: if ((tst->prefix == NULL) && (cur->prefix == NULL))
3499: goto shadowed;
3500: if ((tst->prefix != NULL) && (cur->prefix != NULL) &&
1.128 veillard 3501: (xmlStrEqual(tst->prefix, cur->prefix)))
1.82 daniel 3502: goto shadowed;
3503: tst = tst->next;
3504: }
3505: }
1.19 daniel 3506: return(cur);
1.82 daniel 3507: }
3508: shadowed:
1.19 daniel 3509: cur = cur->next;
3510: }
3511: node = node->parent;
3512: }
1.82 daniel 3513: return(NULL);
3514: }
3515:
3516: /**
3517: * xmlNewReconciliedNs
3518: * @doc: the document
3519: * @tree: a node expected to hold the new namespace
3520: * @ns: the original namespace
3521: *
3522: * This function tries to locate a namespace definition in a tree
3523: * ancestors, or create a new namespace definition node similar to
3524: * @ns trying to reuse the same prefix. However if the given prefix is
3525: * null (default namespace) or reused within the subtree defined by
3526: * @tree or on one of its ancestors then a new prefix is generated.
3527: * Returns the (new) namespace definition or NULL in case of error
3528: */
3529: xmlNsPtr
3530: xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) {
3531: xmlNsPtr def;
3532: xmlChar prefix[50];
3533: int counter = 1;
3534:
3535: if (tree == NULL) {
3536: #ifdef DEBUG_TREE
3537: fprintf(stderr, "xmlNewReconciliedNs : tree == NULL\n");
3538: #endif
3539: return(NULL);
3540: }
3541: if (ns == NULL) {
3542: #ifdef DEBUG_TREE
3543: fprintf(stderr, "xmlNewReconciliedNs : ns == NULL\n");
3544: #endif
3545: return(NULL);
3546: }
3547: /*
3548: * Search an existing namespace definition inherited.
3549: */
3550: def = xmlSearchNsByHref(doc, tree, ns->href);
3551: if (def != NULL)
3552: return(def);
3553:
3554: /*
3555: * Find a close prefix which is not already in use.
3556: * Let's strip namespace prefixes longer than 20 chars !
3557: */
3558: sprintf((char *) prefix, "%.20s", ns->prefix);
3559: def = xmlSearchNs(doc, tree, prefix);
3560: while (def != NULL) {
3561: if (counter > 1000) return(NULL);
3562: sprintf((char *) prefix, "%.20s%d", ns->prefix, counter++);
3563: def = xmlSearchNs(doc, tree, prefix);
3564: }
3565:
3566: /*
3567: * Ok, now we are ready to create a new one.
3568: */
3569: def = xmlNewNs(tree, ns->href, prefix);
3570: return(def);
3571: }
3572:
3573: /**
3574: * xmlReconciliateNs
3575: * @doc: the document
3576: * @tree: a node defining the subtree to reconciliate
3577: *
3578: * This function checks that all the namespaces declared within the given
3579: * tree are properly declared. This is needed for example after Copy or Cut
3580: * and then paste operations. The subtree may still hold pointers to
3581: * namespace declarations outside the subtree or invalid/masked. As much
3582: * as possible the function try tu reuse the existing namespaces found in
3583: * the new environment. If not possible the new namespaces are redeclared
3584: * on @tree at the top of the given subtree.
3585: * Returns the number of namespace declarations created or -1 in case of error.
3586: */
3587: int
3588: xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) {
3589: xmlNsPtr *oldNs = NULL;
3590: xmlNsPtr *newNs = NULL;
3591: int sizeCache = 0;
3592: int nbCache = 0;
3593:
3594: xmlNsPtr n;
3595: xmlNodePtr node = tree;
3596: xmlAttrPtr attr;
3597: int ret = 0, i;
3598:
3599: while (node != NULL) {
3600: /*
3601: * Reconciliate the node namespace
3602: */
3603: if (node->ns != NULL) {
3604: /*
3605: * initialize the cache if needed
3606: */
3607: if (sizeCache == 0) {
3608: sizeCache = 10;
3609: oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3610: sizeof(xmlNsPtr));
3611: if (oldNs == NULL) {
3612: fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3613: return(-1);
3614: }
3615: newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3616: sizeof(xmlNsPtr));
3617: if (newNs == NULL) {
3618: fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3619: xmlFree(oldNs);
3620: return(-1);
3621: }
3622: }
3623: for (i = 0;i < nbCache;i++) {
3624: if (oldNs[i] == node->ns) {
3625: node->ns = newNs[i];
3626: break;
3627: }
3628: }
3629: if (i == nbCache) {
3630: /*
3631: * Ok we need to recreate a new namespace definition
3632: */
3633: n = xmlNewReconciliedNs(doc, tree, node->ns);
3634: if (n != NULL) { /* :-( what if else ??? */
3635: /*
3636: * check if we need to grow the cache buffers.
3637: */
3638: if (sizeCache <= nbCache) {
3639: sizeCache *= 2;
3640: oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
3641: sizeof(xmlNsPtr));
3642: if (oldNs == NULL) {
3643: fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3644: xmlFree(newNs);
3645: return(-1);
3646: }
3647: newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
3648: sizeof(xmlNsPtr));
3649: if (newNs == NULL) {
3650: fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3651: xmlFree(oldNs);
3652: return(-1);
3653: }
3654: }
3655: newNs[nbCache] = n;
3656: oldNs[nbCache++] = node->ns;
3657: node->ns = n;
3658: }
3659: }
3660: }
3661: /*
3662: * now check for namespace hold by attributes on the node.
3663: */
3664: attr = node->properties;
3665: while (attr != NULL) {
3666: if (attr->ns != NULL) {
3667: /*
3668: * initialize the cache if needed
3669: */
3670: if (sizeCache == 0) {
3671: sizeCache = 10;
3672: oldNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3673: sizeof(xmlNsPtr));
3674: if (oldNs == NULL) {
3675: fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3676: return(-1);
3677: }
3678: newNs = (xmlNsPtr *) xmlMalloc(sizeCache *
3679: sizeof(xmlNsPtr));
3680: if (newNs == NULL) {
3681: fprintf(stderr, "xmlReconciliateNs : memory pbm\n");
3682: xmlFree(oldNs);
3683: return(-1);
3684: }
3685: }
3686: for (i = 0;i < nbCache;i++) {
3687: if (oldNs[i] == attr->ns) {
3688: node->ns = newNs[i];
3689: break;
3690: }
3691: }
3692: if (i == nbCache) {
3693: /*
3694: * Ok we need to recreate a new namespace definition
3695: */
3696: n = xmlNewReconciliedNs(doc, tree, attr->ns);
3697: if (n != NULL) { /* :-( what if else ??? */
3698: /*
3699: * check if we need to grow the cache buffers.
3700: */
3701: if (sizeCache <= nbCache) {
3702: sizeCache *= 2;
3703: oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache *
3704: sizeof(xmlNsPtr));
3705: if (oldNs == NULL) {
3706: fprintf(stderr,
3707: "xmlReconciliateNs : memory pbm\n");
3708: xmlFree(newNs);
3709: return(-1);
3710: }
3711: newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache *
3712: sizeof(xmlNsPtr));
3713: if (newNs == NULL) {
3714: fprintf(stderr,
3715: "xmlReconciliateNs : memory pbm\n");
3716: xmlFree(oldNs);
3717: return(-1);
3718: }
3719: }
3720: newNs[nbCache] = n;
3721: oldNs[nbCache++] = attr->ns;
3722: attr->ns = n;
3723: }
3724: }
3725: }
3726: attr = attr->next;
3727: }
3728:
3729: /*
3730: * Browse the full subtree, deep first
3731: */
1.90 daniel 3732: if (node->children != NULL) {
1.82 daniel 3733: /* deep first */
1.90 daniel 3734: node = node->children;
1.82 daniel 3735: } else if ((node != tree) && (node->next != NULL)) {
3736: /* then siblings */
3737: node = node->next;
3738: } else if (node != tree) {
3739: /* go up to parents->next if needed */
3740: while (node != tree) {
3741: if (node->parent != NULL)
3742: node = node->parent;
3743: if ((node != tree) && (node->next != NULL)) {
3744: node = node->next;
3745: break;
3746: }
3747: if (node->parent == NULL) {
3748: node = NULL;
3749: break;
3750: }
3751: }
3752: /* exit condition */
3753: if (node == tree)
3754: node = NULL;
1.19 daniel 3755: }
1.3 veillard 3756: }
1.82 daniel 3757: return(ret);
1.3 veillard 3758: }
3759:
1.23 daniel 3760: /**
1.116 veillard 3761: * xmlHasProp:
3762: * @node: the node
3763: * @name: the attribute name
3764: *
3765: * Search an attribute associated to a node
3766: * This function also looks in DTD attribute declaration for #FIXED or
3767: * default declaration values unless DTD use has been turned off.
3768: *
3769: * Returns the attribute or the attribute declaration or NULL if
3770: * neither was found.
3771: */
3772: xmlAttrPtr
3773: xmlHasProp(xmlNodePtr node, const xmlChar *name) {
3774: xmlAttrPtr prop;
3775: xmlDocPtr doc;
3776:
3777: if ((node == NULL) || (name == NULL)) return(NULL);
3778: /*
3779: * Check on the properties attached to the node
3780: */
3781: prop = node->properties;
3782: while (prop != NULL) {
1.128 veillard 3783: if (xmlStrEqual(prop->name, name)) {
1.116 veillard 3784: return(prop);
3785: }
3786: prop = prop->next;
3787: }
3788: if (!xmlCheckDTD) return(NULL);
3789:
3790: /*
3791: * Check if there is a default declaration in the internal
3792: * or external subsets
3793: */
3794: doc = node->doc;
3795: if (doc != NULL) {
3796: xmlAttributePtr attrDecl;
3797: if (doc->intSubset != NULL) {
3798: attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3799: if ((attrDecl == NULL) && (doc->extSubset != NULL))
3800: attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
3801: if (attrDecl != NULL)
3802: return((xmlAttrPtr) attrDecl);
3803: }
3804: }
3805: return(NULL);
3806: }
3807:
3808: /**
1.23 daniel 3809: * xmlGetProp:
3810: * @node: the node
3811: * @name: the attribute name
3812: *
3813: * Search and get the value of an attribute associated to a node
3814: * This does the entity substitution.
1.74 daniel 3815: * This function looks in DTD attribute declaration for #FIXED or
3816: * default declaration values unless DTD use has been turned off.
3817: *
1.36 daniel 3818: * Returns the attribute value or NULL if not found.
1.69 daniel 3819: * It's up to the caller to free the memory.
1.9 veillard 3820: */
1.69 daniel 3821: xmlChar *
3822: xmlGetProp(xmlNodePtr node, const xmlChar *name) {
1.74 daniel 3823: xmlAttrPtr prop;
3824: xmlDocPtr doc;
1.9 veillard 3825:
1.74 daniel 3826: if ((node == NULL) || (name == NULL)) return(NULL);
3827: /*
3828: * Check on the properties attached to the node
3829: */
3830: prop = node->properties;
1.9 veillard 3831: while (prop != NULL) {
1.128 veillard 3832: if (xmlStrEqual(prop->name, name)) {
1.61 daniel 3833: xmlChar *ret;
1.34 daniel 3834:
1.90 daniel 3835: ret = xmlNodeListGetString(node->doc, prop->children, 1);
1.61 daniel 3836: if (ret == NULL) return(xmlStrdup((xmlChar *)""));
1.34 daniel 3837: return(ret);
3838: }
1.9 veillard 3839: prop = prop->next;
3840: }
1.74 daniel 3841: if (!xmlCheckDTD) return(NULL);
3842:
3843: /*
3844: * Check if there is a default declaration in the internal
3845: * or external subsets
3846: */
3847: doc = node->doc;
3848: if (doc != NULL) {
3849: xmlAttributePtr attrDecl;
3850: if (doc->intSubset != NULL) {
3851: attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3852: if ((attrDecl == NULL) && (doc->extSubset != NULL))
3853: attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
1.86 daniel 3854: if (attrDecl != NULL)
3855: return(xmlStrdup(attrDecl->defaultValue));
1.74 daniel 3856: }
3857: }
1.10 veillard 3858: return(NULL);
1.13 daniel 3859: }
3860:
1.23 daniel 3861: /**
1.73 daniel 3862: * xmlGetNsProp:
3863: * @node: the node
3864: * @name: the attribute name
3865: * @namespace: the URI of the namespace
3866: *
3867: * Search and get the value of an attribute associated to a node
3868: * This attribute has to be anchored in the namespace specified.
3869: * This does the entity substitution.
1.74 daniel 3870: * This function looks in DTD attribute declaration for #FIXED or
3871: * default declaration values unless DTD use has been turned off.
1.73 daniel 3872: *
3873: * Returns the attribute value or NULL if not found.
3874: * It's up to the caller to free the memory.
3875: */
3876: xmlChar *
3877: xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) {
3878: xmlAttrPtr prop = node->properties;
1.74 daniel 3879: xmlDocPtr doc;
3880: xmlNsPtr ns;
1.73 daniel 3881:
3882: if (namespace == NULL)
3883: return(xmlGetProp(node, name));
3884: while (prop != NULL) {
1.79 daniel 3885: /*
3886: * One need to have
3887: * - same attribute names
3888: * - and the attribute carrying that namespace
3889: * or
3890: * no namespace on the attribute and the element carrying it
3891: */
1.128 veillard 3892: if ((xmlStrEqual(prop->name, name)) &&
1.79 daniel 3893: (((prop->ns == NULL) && (node->ns != NULL) &&
1.128 veillard 3894: (xmlStrEqual(node->ns->href, namespace))) ||
3895: ((prop->ns != NULL) && (xmlStrEqual(prop->ns->href, namespace))))) {
1.73 daniel 3896: xmlChar *ret;
3897:
1.90 daniel 3898: ret = xmlNodeListGetString(node->doc, prop->children, 1);
1.73 daniel 3899: if (ret == NULL) return(xmlStrdup((xmlChar *)""));
3900: return(ret);
3901: }
3902: prop = prop->next;
3903: }
1.74 daniel 3904: if (!xmlCheckDTD) return(NULL);
3905:
3906: /*
3907: * Check if there is a default declaration in the internal
3908: * or external subsets
3909: */
3910: doc = node->doc;
3911: if (doc != NULL) {
3912: xmlAttributePtr attrDecl;
3913: if (doc->intSubset != NULL) {
3914: attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
3915: if ((attrDecl == NULL) && (doc->extSubset != NULL))
3916: attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
3917:
3918: if (attrDecl->prefix != NULL) {
3919: /*
3920: * The DTD declaration only allows a prefix search
3921: */
3922: ns = xmlSearchNs(doc, node, attrDecl->prefix);
1.128 veillard 3923: if ((ns != NULL) && (xmlStrEqual(ns->href, namespace)))
1.74 daniel 3924: return(xmlStrdup(attrDecl->defaultValue));
3925: }
3926: }
3927: }
1.73 daniel 3928: return(NULL);
3929: }
3930:
3931: /**
1.23 daniel 3932: * xmlSetProp:
3933: * @node: the node
3934: * @name: the attribute name
3935: * @value: the attribute value
3936: *
3937: * Set (or reset) an attribute carried by a node.
1.36 daniel 3938: * Returns the attribute pointer.
1.13 daniel 3939: */
1.28 daniel 3940: xmlAttrPtr
1.61 daniel 3941: xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
1.20 daniel 3942: xmlAttrPtr prop = node->properties;
1.13 daniel 3943:
3944: while (prop != NULL) {
1.128 veillard 3945: if (xmlStrEqual(prop->name, name)) {
1.90 daniel 3946: if (prop->children != NULL)
3947: xmlFreeNodeList(prop->children);
3948: prop->children = NULL;
1.67 daniel 3949: if (value != NULL) {
3950: xmlChar *buffer;
1.94 daniel 3951: xmlNodePtr tmp;
3952:
1.67 daniel 3953: buffer = xmlEncodeEntitiesReentrant(node->doc, value);
1.90 daniel 3954: prop->children = xmlStringGetNodeList(node->doc, buffer);
1.94 daniel 3955: tmp = prop->children;
3956: while (tmp != NULL) {
3957: tmp->parent = (xmlNodePtr) prop;
3958: if (tmp->next == NULL)
3959: prop->last = tmp;
3960: tmp = tmp->next;
3961: }
1.67 daniel 3962: xmlFree(buffer);
3963: }
1.13 daniel 3964: return(prop);
3965: }
3966: prop = prop->next;
3967: }
3968: prop = xmlNewProp(node, name, value);
3969: return(prop);
1.9 veillard 3970: }
3971:
1.23 daniel 3972: /**
3973: * xmlNodeIsText:
3974: * @node: the node
3975: *
3976: * Is this node a Text node ?
1.36 daniel 3977: * Returns 1 yes, 0 no
1.21 daniel 3978: */
1.28 daniel 3979: int
3980: xmlNodeIsText(xmlNodePtr node) {
1.21 daniel 3981: if (node == NULL) return(0);
3982:
1.23 daniel 3983: if (node->type == XML_TEXT_NODE) return(1);
1.21 daniel 3984: return(0);
3985: }
3986:
1.23 daniel 3987: /**
1.99 daniel 3988: * xmlIsBlankNode:
3989: * @node: the node
3990: *
1.113 veillard 3991: * Checks whether this node is an empty or whitespace only
3992: * (and possibly ignorable) text-node.
3993: *
1.99 daniel 3994: * Returns 1 yes, 0 no
3995: */
3996: int
3997: xmlIsBlankNode(xmlNodePtr node) {
3998: xmlChar *cur;
3999: if (node == NULL) return(0);
4000:
4001: if (node->type != XML_TEXT_NODE) return(0);
1.129 veillard 4002: if (node->content == NULL) return(1);
1.99 daniel 4003: cur = node->content;
4004: while (*cur != 0) {
4005: if (!IS_BLANK(*cur)) return(0);
4006: cur++;
4007: }
4008:
4009: return(1);
4010: }
4011:
4012: /**
1.36 daniel 4013: * xmlTextConcat:
1.23 daniel 4014: * @node: the node
4015: * @content: the content
4016: * @len: @content lenght
4017: *
4018: * Concat the given string at the end of the existing node content
1.21 daniel 4019: */
1.23 daniel 4020:
1.28 daniel 4021: void
1.61 daniel 4022: xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) {
1.21 daniel 4023: if (node == NULL) return;
4024:
1.82 daniel 4025: if ((node->type != XML_TEXT_NODE) &&
4026: (node->type != XML_CDATA_SECTION_NODE)) {
1.86 daniel 4027: #ifdef DEBUG_TREE
1.82 daniel 4028: fprintf(stderr, "xmlTextConcat: node is not text nor cdata\n");
1.86 daniel 4029: #endif
1.21 daniel 4030: return;
4031: }
1.70 daniel 4032: #ifndef XML_USE_BUFFER_CONTENT
1.21 daniel 4033: node->content = xmlStrncat(node->content, content, len);
1.70 daniel 4034: #else
4035: xmlBufferAdd(node->content, content, len);
4036: #endif
1.21 daniel 4037: }
4038:
1.1 veillard 4039: /************************************************************************
4040: * *
1.8 veillard 4041: * Output : to a FILE or in memory *
1.1 veillard 4042: * *
4043: ************************************************************************/
4044:
1.38 daniel 4045: #define BASE_BUFFER_SIZE 4000
1.8 veillard 4046:
1.23 daniel 4047: /**
1.38 daniel 4048: * xmlBufferCreate:
4049: *
4050: * routine to create an XML buffer.
4051: * returns the new structure.
4052: */
4053: xmlBufferPtr
4054: xmlBufferCreate(void) {
4055: xmlBufferPtr ret;
4056:
1.57 daniel 4057: ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
1.38 daniel 4058: if (ret == NULL) {
4059: fprintf(stderr, "xmlBufferCreate : out of memory!\n");
4060: return(NULL);
4061: }
4062: ret->use = 0;
4063: ret->size = BASE_BUFFER_SIZE;
1.72 daniel 4064: ret->alloc = xmlBufferAllocScheme;
1.61 daniel 4065: ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
1.38 daniel 4066: if (ret->content == NULL) {
4067: fprintf(stderr, "xmlBufferCreate : out of memory!\n");
1.57 daniel 4068: xmlFree(ret);
1.38 daniel 4069: return(NULL);
4070: }
4071: ret->content[0] = 0;
4072: return(ret);
4073: }
4074:
4075: /**
1.70 daniel 4076: * xmlBufferCreateSize:
4077: * @size: initial size of buffer
4078: *
4079: * routine to create an XML buffer.
4080: * returns the new structure.
4081: */
4082: xmlBufferPtr
4083: xmlBufferCreateSize(size_t size) {
4084: xmlBufferPtr ret;
4085:
4086: ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
4087: if (ret == NULL) {
4088: fprintf(stderr, "xmlBufferCreate : out of memory!\n");
4089: return(NULL);
4090: }
4091: ret->use = 0;
1.72 daniel 4092: ret->alloc = xmlBufferAllocScheme;
1.70 daniel 4093: ret->size = (size ? size+2 : 0); /* +1 for ending null */
1.72 daniel 4094: if (ret->size){
1.70 daniel 4095: ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar));
4096: if (ret->content == NULL) {
4097: fprintf(stderr, "xmlBufferCreate : out of memory!\n");
4098: xmlFree(ret);
4099: return(NULL);
4100: }
4101: ret->content[0] = 0;
4102: } else
4103: ret->content = NULL;
4104: return(ret);
4105: }
4106:
4107: /**
1.104 daniel 4108: * xmlBufferSetAllocationScheme:
1.70 daniel 4109: * @buf: the buffer to free
4110: * @scheme: allocation scheme to use
4111: *
4112: * Sets the allocation scheme for this buffer
4113: */
4114: void
4115: xmlBufferSetAllocationScheme(xmlBufferPtr buf,
4116: xmlBufferAllocationScheme scheme) {
4117: if (buf == NULL) {
1.86 daniel 4118: #ifdef DEBUG_BUFFER
1.70 daniel 4119: fprintf(stderr, "xmlBufferSetAllocationScheme: buf == NULL\n");
1.86 daniel 4120: #endif
1.70 daniel 4121: return;
4122: }
4123:
4124: buf->alloc = scheme;
4125: }
4126:
4127: /**
1.38 daniel 4128: * xmlBufferFree:
4129: * @buf: the buffer to free
4130: *
4131: * Frees an XML buffer.
4132: */
4133: void
4134: xmlBufferFree(xmlBufferPtr buf) {
4135: if (buf == NULL) {
1.86 daniel 4136: #ifdef DEBUG_BUFFER
1.38 daniel 4137: fprintf(stderr, "xmlBufferFree: buf == NULL\n");
1.86 daniel 4138: #endif
1.38 daniel 4139: return;
4140: }
1.71 daniel 4141: if (buf->content != NULL) {
1.70 daniel 4142: #ifndef XML_USE_BUFFER_CONTENT
1.38 daniel 4143: memset(buf->content, -1, BASE_BUFFER_SIZE);
1.70 daniel 4144: #else
4145: memset(buf->content, -1, buf->size);
4146: #endif
1.57 daniel 4147: xmlFree(buf->content);
1.38 daniel 4148: }
4149: memset(buf, -1, sizeof(xmlBuffer));
1.57 daniel 4150: xmlFree(buf);
1.38 daniel 4151: }
4152:
4153: /**
1.47 daniel 4154: * xmlBufferEmpty:
4155: * @buf: the buffer
4156: *
4157: * empty a buffer.
4158: */
4159: void
4160: xmlBufferEmpty(xmlBufferPtr buf) {
1.124 veillard 4161: if (buf->content == NULL) return;
1.47 daniel 4162: buf->use = 0;
4163: memset(buf->content, -1, buf->size);/* just for debug */
4164: }
4165:
4166: /**
4167: * xmlBufferShrink:
4168: * @buf: the buffer to dump
1.61 daniel 4169: * @len: the number of xmlChar to remove
1.47 daniel 4170: *
4171: * Remove the beginning of an XML buffer.
4172: *
1.61 daniel 4173: * Returns the number of xmlChar removed, or -1 in case of failure.
1.47 daniel 4174: */
4175: int
1.127 veillard 4176: xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
1.47 daniel 4177: if (len == 0) return(0);
4178: if (len > buf->use) return(-1);
4179:
4180: buf->use -= len;
1.61 daniel 4181: memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar));
1.47 daniel 4182:
4183: buf->content[buf->use] = 0;
4184: return(len);
4185: }
4186:
4187: /**
1.105 daniel 4188: * xmlBufferGrow:
4189: * @buf: the buffer
4190: * @len: the minimum free sie to allocate
4191: *
4192: * Grow the available space of an XML buffer.
4193: *
4194: * Returns the new available space or -1 in case of error
4195: */
4196: int
1.127 veillard 4197: xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
1.105 daniel 4198: int size;
4199: xmlChar *newbuf;
4200:
4201: if (len <= buf->use) return(0);
4202:
1.109 daniel 4203: size = buf->use + len + 100;
1.105 daniel 4204:
1.112 veillard 4205: newbuf = (xmlChar *) xmlRealloc(buf->content, size);
1.105 daniel 4206: if (newbuf == NULL) return(-1);
4207: buf->content = newbuf;
4208: buf->size = size;
4209: return(buf->size - buf->use);
4210: }
4211:
4212: /**
1.38 daniel 4213: * xmlBufferDump:
4214: * @file: the file output
4215: * @buf: the buffer to dump
4216: *
4217: * Dumps an XML buffer to a FILE *.
1.61 daniel 4218: * Returns the number of xmlChar written
1.38 daniel 4219: */
4220: int
4221: xmlBufferDump(FILE *file, xmlBufferPtr buf) {
4222: int ret;
4223:
4224: if (buf == NULL) {
1.86 daniel 4225: #ifdef DEBUG_BUFFER
1.38 daniel 4226: fprintf(stderr, "xmlBufferDump: buf == NULL\n");
1.86 daniel 4227: #endif
1.38 daniel 4228: return(0);
4229: }
4230: if (buf->content == NULL) {
1.86 daniel 4231: #ifdef DEBUG_BUFFER
1.38 daniel 4232: fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
1.86 daniel 4233: #endif
1.38 daniel 4234: return(0);
4235: }
4236: if (file == NULL) file = stdout;
1.61 daniel 4237: ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file);
1.38 daniel 4238: return(ret);
4239: }
4240:
4241: /**
1.70 daniel 4242: * xmlBufferContent:
4243: * @buf: the buffer to resize
4244: *
4245: * Returns the internal content
4246: */
4247:
4248: const xmlChar*
4249: xmlBufferContent(const xmlBufferPtr buf)
4250: {
4251: if(!buf)
4252: return NULL;
4253:
4254: return buf->content;
4255: }
4256:
4257: /**
4258: * xmlBufferLength:
4259: * @buf: the buffer
4260: *
4261: * Returns the length of data in the internal content
4262: */
4263:
4264: int
4265: xmlBufferLength(const xmlBufferPtr buf)
4266: {
4267: if(!buf)
4268: return 0;
4269:
4270: return buf->use;
4271: }
4272:
4273: /**
4274: * xmlBufferResize:
4275: * @buf: the buffer to resize
1.127 veillard 4276: * @size: the desired size
1.70 daniel 4277: *
1.127 veillard 4278: * Resize a buffer to accomodate minimum size of @size.
1.70 daniel 4279: *
4280: * Returns 0 in case of problems, 1 otherwise
4281: */
4282: int
1.127 veillard 4283: xmlBufferResize(xmlBufferPtr buf, unsigned int size)
1.70 daniel 4284: {
1.127 veillard 4285: unsigned int newSize;
1.70 daniel 4286: xmlChar* rebuf = NULL;
4287:
1.127 veillard 4288: /*take care of empty case*/
4289: newSize = (buf->size ? buf->size*2 : size);
4290:
1.70 daniel 4291: /* Don't resize if we don't have to */
1.127 veillard 4292: if (size < buf->size)
1.70 daniel 4293: return 1;
4294:
4295: /* figure out new size */
1.127 veillard 4296: switch (buf->alloc){
1.70 daniel 4297: case XML_BUFFER_ALLOC_DOUBLEIT:
1.127 veillard 4298: while (size > newSize) newSize *= 2;
1.70 daniel 4299: break;
4300: case XML_BUFFER_ALLOC_EXACT:
4301: newSize = size+10;
4302: break;
4303: default:
4304: newSize = size+10;
4305: break;
4306: }
4307:
4308: if (buf->content == NULL)
4309: rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar));
4310: else
4311: rebuf = (xmlChar *) xmlRealloc(buf->content,
4312: newSize * sizeof(xmlChar));
4313: if (rebuf == NULL) {
4314: fprintf(stderr, "xmlBufferAdd : out of memory!\n");
4315: return 0;
4316: }
4317: buf->content = rebuf;
4318: buf->size = newSize;
4319:
4320: return 1;
4321: }
1.127 veillard 4322:
1.70 daniel 4323: /**
1.38 daniel 4324: * xmlBufferAdd:
4325: * @buf: the buffer to dump
1.61 daniel 4326: * @str: the xmlChar string
4327: * @len: the number of xmlChar to add
1.38 daniel 4328: *
1.74 daniel 4329: * Add a string range to an XML buffer. if len == -1, the lenght of
4330: * str is recomputed.
1.38 daniel 4331: */
4332: void
1.61 daniel 4333: xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
1.127 veillard 4334: unsigned int needSize;
1.38 daniel 4335:
4336: if (str == NULL) {
1.86 daniel 4337: #ifdef DEBUG_BUFFER
1.38 daniel 4338: fprintf(stderr, "xmlBufferAdd: str == NULL\n");
1.86 daniel 4339: #endif
1.38 daniel 4340: return;
4341: }
1.74 daniel 4342: if (len < -1) {
1.86 daniel 4343: #ifdef DEBUG_BUFFER
1.74 daniel 4344: fprintf(stderr, "xmlBufferAdd: len < 0\n");
1.86 daniel 4345: #endif
1.74 daniel 4346: return;
4347: }
4348: if (len == 0) return;
1.70 daniel 4349:
1.82 daniel 4350: if (len < 0)
1.89 daniel 4351: len = xmlStrlen(str);
1.70 daniel 4352:
1.47 daniel 4353: if (len <= 0) return;
4354:
1.70 daniel 4355: needSize = buf->use + len + 2;
1.127 veillard 4356: if (needSize > buf->size){
4357: if (!xmlBufferResize(buf, needSize)){
1.70 daniel 4358: fprintf(stderr, "xmlBufferAdd : out of memory!\n");
4359: return;
4360: }
4361: }
1.47 daniel 4362:
1.70 daniel 4363: memmove(&buf->content[buf->use], str, len*sizeof(xmlChar));
1.47 daniel 4364: buf->use += len;
4365: buf->content[buf->use] = 0;
1.38 daniel 4366: }
4367:
4368: /**
1.109 daniel 4369: * xmlBufferAddHead:
4370: * @buf: the buffer
4371: * @str: the xmlChar string
4372: * @len: the number of xmlChar to add
4373: *
4374: * Add a string range to the beginning of an XML buffer.
4375: * if len == -1, the lenght of @str is recomputed.
4376: */
4377: void
4378: xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
1.127 veillard 4379: unsigned int needSize;
1.109 daniel 4380:
4381: if (str == NULL) {
4382: #ifdef DEBUG_BUFFER
4383: fprintf(stderr, "xmlBufferAdd: str == NULL\n");
4384: #endif
4385: return;
4386: }
4387: if (len < -1) {
4388: #ifdef DEBUG_BUFFER
4389: fprintf(stderr, "xmlBufferAdd: len < 0\n");
4390: #endif
4391: return;
4392: }
4393: if (len == 0) return;
4394:
4395: if (len < 0)
4396: len = xmlStrlen(str);
4397:
4398: if (len <= 0) return;
4399:
4400: needSize = buf->use + len + 2;
1.127 veillard 4401: if (needSize > buf->size){
4402: if (!xmlBufferResize(buf, needSize)){
1.109 daniel 4403: fprintf(stderr, "xmlBufferAddHead : out of memory!\n");
4404: return;
4405: }
4406: }
4407:
4408: memmove(&buf->content[len], &buf->content[0], buf->use * sizeof(xmlChar));
4409: memmove(&buf->content[0], str, len * sizeof(xmlChar));
4410: buf->use += len;
4411: buf->content[buf->use] = 0;
4412: }
4413:
4414: /**
1.38 daniel 4415: * xmlBufferCat:
4416: * @buf: the buffer to dump
1.61 daniel 4417: * @str: the xmlChar string
1.23 daniel 4418: *
1.38 daniel 4419: * Append a zero terminated string to an XML buffer.
1.23 daniel 4420: */
1.28 daniel 4421: void
1.61 daniel 4422: xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
1.70 daniel 4423: if (str != NULL)
4424: xmlBufferAdd(buf, str, -1);
1.8 veillard 4425: }
4426:
1.23 daniel 4427: /**
1.38 daniel 4428: * xmlBufferCCat:
4429: * @buf: the buffer to dump
4430: * @str: the C char string
1.23 daniel 4431: *
1.38 daniel 4432: * Append a zero terminated C string to an XML buffer.
1.23 daniel 4433: */
1.28 daniel 4434: void
1.38 daniel 4435: xmlBufferCCat(xmlBufferPtr buf, const char *str) {
1.21 daniel 4436: const char *cur;
1.8 veillard 4437:
1.38 daniel 4438: if (str == NULL) {
1.86 daniel 4439: #ifdef DEBUG_BUFFER
1.38 daniel 4440: fprintf(stderr, "xmlBufferAdd: str == NULL\n");
1.86 daniel 4441: #endif
1.38 daniel 4442: return;
4443: }
4444: for (cur = str;*cur != 0;cur++) {
4445: if (buf->use + 10 >= buf->size) {
1.127 veillard 4446: if (!xmlBufferResize(buf, buf->use+10)){
1.70 daniel 4447: fprintf(stderr, "xmlBufferCCat : out of memory!\n");
4448: return;
4449: }
4450: }
1.38 daniel 4451: buf->content[buf->use++] = *cur;
1.8 veillard 4452: }
4453: }
4454:
1.23 daniel 4455: /**
1.38 daniel 4456: * xmlBufferWriteCHAR:
4457: * @buf: the XML buffer
4458: * @string: the string to add
4459: *
4460: * routine which manage and grows an output buffer. This one add
1.61 daniel 4461: * xmlChars at the end of the buffer.
1.38 daniel 4462: */
4463: void
1.61 daniel 4464: xmlBufferWriteCHAR(xmlBufferPtr buf, const xmlChar *string) {
1.38 daniel 4465: xmlBufferCat(buf, string);
4466: }
4467:
4468: /**
4469: * xmlBufferWriteChar:
1.42 daniel 4470: * @buf: the XML buffer output
1.38 daniel 4471: * @string: the string to add
4472: *
4473: * routine which manage and grows an output buffer. This one add
4474: * C chars at the end of the array.
4475: */
4476: void
4477: xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
4478: xmlBufferCCat(buf, string);
4479: }
4480:
4481:
4482: /**
1.43 daniel 4483: * xmlBufferWriteQuotedString:
4484: * @buf: the XML buffer output
4485: * @string: the string to add
4486: *
4487: * routine which manage and grows an output buffer. This one writes
1.61 daniel 4488: * a quoted or double quoted xmlChar string, checking first if it holds
1.43 daniel 4489: * quote or double-quotes internally
4490: */
4491: void
1.61 daniel 4492: xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
1.53 daniel 4493: if (xmlStrchr(string, '"')) {
4494: if (xmlStrchr(string, '\'')) {
1.86 daniel 4495: #ifdef DEBUG_BUFFER
1.43 daniel 4496: fprintf(stderr,
4497: "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
1.86 daniel 4498: #endif
1.43 daniel 4499: }
4500: xmlBufferCCat(buf, "'");
4501: xmlBufferCat(buf, string);
4502: xmlBufferCCat(buf, "'");
4503: } else {
4504: xmlBufferCCat(buf, "\"");
4505: xmlBufferCat(buf, string);
4506: xmlBufferCCat(buf, "\"");
4507: }
4508: }
4509:
4510:
1.106 daniel 4511: /************************************************************************
4512: * *
4513: * Dumping XML tree content to a simple buffer *
4514: * *
4515: ************************************************************************/
4516:
1.125 veillard 4517: void
1.99 daniel 4518: xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4519: int format);
4520: static void
4521: xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4522: int format);
4523: void
4524: htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur);
4525:
1.43 daniel 4526: /**
1.23 daniel 4527: * xmlGlobalNsDump:
1.42 daniel 4528: * @buf: the XML buffer output
1.23 daniel 4529: * @cur: a namespace
4530: *
4531: * Dump a global Namespace, this is the old version based on PIs.
1.1 veillard 4532: */
1.28 daniel 4533: static void
1.38 daniel 4534: xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.1 veillard 4535: if (cur == NULL) {
1.86 daniel 4536: #ifdef DEBUG_TREE
1.19 daniel 4537: fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
1.86 daniel 4538: #endif
1.1 veillard 4539: return;
4540: }
1.19 daniel 4541: if (cur->type == XML_GLOBAL_NAMESPACE) {
1.38 daniel 4542: xmlBufferWriteChar(buf, "<?namespace");
1.12 daniel 4543: if (cur->href != NULL) {
1.43 daniel 4544: xmlBufferWriteChar(buf, " href=");
4545: xmlBufferWriteQuotedString(buf, cur->href);
1.12 daniel 4546: }
1.16 daniel 4547: if (cur->prefix != NULL) {
1.43 daniel 4548: xmlBufferWriteChar(buf, " AS=");
4549: xmlBufferWriteQuotedString(buf, cur->prefix);
1.12 daniel 4550: }
1.38 daniel 4551: xmlBufferWriteChar(buf, "?>\n");
1.19 daniel 4552: }
4553: }
4554:
1.23 daniel 4555: /**
4556: * xmlGlobalNsListDump:
1.42 daniel 4557: * @buf: the XML buffer output
1.23 daniel 4558: * @cur: the first namespace
4559: *
4560: * Dump a list of global Namespace, this is the old version based on PIs.
1.19 daniel 4561: */
1.28 daniel 4562: static void
1.38 daniel 4563: xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19 daniel 4564: while (cur != NULL) {
1.38 daniel 4565: xmlGlobalNsDump(buf, cur);
1.19 daniel 4566: cur = cur->next;
4567: }
4568: }
4569:
1.23 daniel 4570: /**
4571: * xmlNsDump:
1.42 daniel 4572: * @buf: the XML buffer output
1.23 daniel 4573: * @cur: a namespace
4574: *
1.19 daniel 4575: * Dump a local Namespace definition.
1.23 daniel 4576: * Should be called in the context of attributes dumps.
1.19 daniel 4577: */
1.28 daniel 4578: static void
1.38 daniel 4579: xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19 daniel 4580: if (cur == NULL) {
1.86 daniel 4581: #ifdef DEBUG_TREE
1.19 daniel 4582: fprintf(stderr, "xmlNsDump : Ns == NULL\n");
1.86 daniel 4583: #endif
1.19 daniel 4584: return;
4585: }
4586: if (cur->type == XML_LOCAL_NAMESPACE) {
4587: /* Within the context of an element attributes */
1.16 daniel 4588: if (cur->prefix != NULL) {
1.38 daniel 4589: xmlBufferWriteChar(buf, " xmlns:");
4590: xmlBufferWriteCHAR(buf, cur->prefix);
1.19 daniel 4591: } else
1.38 daniel 4592: xmlBufferWriteChar(buf, " xmlns");
1.43 daniel 4593: xmlBufferWriteChar(buf, "=");
4594: xmlBufferWriteQuotedString(buf, cur->href);
1.19 daniel 4595: }
4596: }
4597:
1.23 daniel 4598: /**
4599: * xmlNsListDump:
1.42 daniel 4600: * @buf: the XML buffer output
1.23 daniel 4601: * @cur: the first namespace
4602: *
4603: * Dump a list of local Namespace definitions.
4604: * Should be called in the context of attributes dumps.
1.19 daniel 4605: */
1.28 daniel 4606: static void
1.38 daniel 4607: xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19 daniel 4608: while (cur != NULL) {
1.38 daniel 4609: xmlNsDump(buf, cur);
1.19 daniel 4610: cur = cur->next;
1.8 veillard 4611: }
1.1 veillard 4612: }
4613:
1.23 daniel 4614: /**
4615: * xmlDtdDump:
1.42 daniel 4616: * @buf: the XML buffer output
1.23 daniel 4617: * @doc: the document
4618: *
4619: * Dump the XML document DTD, if any.
1.17 daniel 4620: */
1.28 daniel 4621: static void
1.92 daniel 4622: xmlDtdDump(xmlBufferPtr buf, xmlDtdPtr dtd) {
4623: if (dtd == NULL) {
1.86 daniel 4624: #ifdef DEBUG_TREE
1.31 daniel 4625: fprintf(stderr, "xmlDtdDump : no internal subset\n");
1.86 daniel 4626: #endif
1.17 daniel 4627: return;
4628: }
1.38 daniel 4629: xmlBufferWriteChar(buf, "<!DOCTYPE ");
1.92 daniel 4630: xmlBufferWriteCHAR(buf, dtd->name);
4631: if (dtd->ExternalID != NULL) {
1.43 daniel 4632: xmlBufferWriteChar(buf, " PUBLIC ");
1.92 daniel 4633: xmlBufferWriteQuotedString(buf, dtd->ExternalID);
1.43 daniel 4634: xmlBufferWriteChar(buf, " ");
1.92 daniel 4635: xmlBufferWriteQuotedString(buf, dtd->SystemID);
4636: } else if (dtd->SystemID != NULL) {
1.43 daniel 4637: xmlBufferWriteChar(buf, " SYSTEM ");
1.92 daniel 4638: xmlBufferWriteQuotedString(buf, dtd->SystemID);
1.17 daniel 4639: }
1.92 daniel 4640: if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
4641: (dtd->attributes == NULL) && (dtd->notations == NULL)) {
4642: xmlBufferWriteChar(buf, ">");
1.21 daniel 4643: return;
4644: }
1.38 daniel 4645: xmlBufferWriteChar(buf, " [\n");
1.99 daniel 4646: xmlNodeListDump(buf, dtd->doc, dtd->children, -1, 0);
4647: #if 0
1.92 daniel 4648: if (dtd->entities != NULL)
4649: xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) dtd->entities);
4650: if (dtd->notations != NULL)
4651: xmlDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations);
4652: if (dtd->elements != NULL)
4653: xmlDumpElementTable(buf, (xmlElementTablePtr) dtd->elements);
4654: if (dtd->attributes != NULL)
4655: xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) dtd->attributes);
1.99 daniel 4656: #endif
4657: xmlBufferWriteChar(buf, "]>");
1.17 daniel 4658: }
4659:
1.23 daniel 4660: /**
4661: * xmlAttrDump:
1.42 daniel 4662: * @buf: the XML buffer output
1.23 daniel 4663: * @doc: the document
4664: * @cur: the attribute pointer
4665: *
4666: * Dump an XML attribute
1.1 veillard 4667: */
1.28 daniel 4668: static void
1.38 daniel 4669: xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
1.61 daniel 4670: xmlChar *value;
1.1 veillard 4671:
4672: if (cur == NULL) {
1.86 daniel 4673: #ifdef DEBUG_TREE
1.20 daniel 4674: fprintf(stderr, "xmlAttrDump : property == NULL\n");
1.86 daniel 4675: #endif
1.1 veillard 4676: return;
4677: }
1.38 daniel 4678: xmlBufferWriteChar(buf, " ");
1.56 daniel 4679: if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
4680: xmlBufferWriteCHAR(buf, cur->ns->prefix);
4681: xmlBufferWriteChar(buf, ":");
4682: }
1.38 daniel 4683: xmlBufferWriteCHAR(buf, cur->name);
1.90 daniel 4684: value = xmlNodeListGetString(doc, cur->children, 0);
1.23 daniel 4685: if (value) {
1.43 daniel 4686: xmlBufferWriteChar(buf, "=");
4687: xmlBufferWriteQuotedString(buf, value);
1.57 daniel 4688: xmlFree(value);
1.34 daniel 4689: } else {
1.38 daniel 4690: xmlBufferWriteChar(buf, "=\"\"");
1.3 veillard 4691: }
1.8 veillard 4692: }
4693:
1.23 daniel 4694: /**
4695: * xmlAttrListDump:
1.42 daniel 4696: * @buf: the XML buffer output
1.23 daniel 4697: * @doc: the document
4698: * @cur: the first attribute pointer
4699: *
4700: * Dump a list of XML attributes
1.8 veillard 4701: */
1.28 daniel 4702: static void
1.38 daniel 4703: xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
1.8 veillard 4704: if (cur == NULL) {
1.86 daniel 4705: #ifdef DEBUG_TREE
1.20 daniel 4706: fprintf(stderr, "xmlAttrListDump : property == NULL\n");
1.86 daniel 4707: #endif
1.1 veillard 4708: return;
4709: }
1.8 veillard 4710: while (cur != NULL) {
1.38 daniel 4711: xmlAttrDump(buf, doc, cur);
1.8 veillard 4712: cur = cur->next;
1.1 veillard 4713: }
4714: }
4715:
4716:
1.82 daniel 4717:
1.23 daniel 4718: /**
4719: * xmlNodeListDump:
1.42 daniel 4720: * @buf: the XML buffer output
1.23 daniel 4721: * @doc: the document
4722: * @cur: the first node
4723: * @level: the imbrication level for indenting
1.64 daniel 4724: * @format: is formatting allowed
1.23 daniel 4725: *
4726: * Dump an XML node list, recursive behaviour,children are printed too.
4727: */
1.28 daniel 4728: static void
1.64 daniel 4729: xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4730: int format) {
4731: int i;
1.25 daniel 4732:
1.1 veillard 4733: if (cur == NULL) {
1.86 daniel 4734: #ifdef DEBUG_TREE
1.8 veillard 4735: fprintf(stderr, "xmlNodeListDump : node == NULL\n");
1.86 daniel 4736: #endif
1.1 veillard 4737: return;
4738: }
1.8 veillard 4739: while (cur != NULL) {
1.64 daniel 4740: if ((format) && (xmlIndentTreeOutput) &&
4741: (cur->type == XML_ELEMENT_NODE))
4742: for (i = 0;i < level;i++)
4743: xmlBufferWriteChar(buf, " ");
4744: xmlNodeDump(buf, doc, cur, level, format);
4745: if (format) {
4746: xmlBufferWriteChar(buf, "\n");
1.25 daniel 4747: }
1.8 veillard 4748: cur = cur->next;
1.3 veillard 4749: }
1.1 veillard 4750: }
4751:
1.23 daniel 4752: /**
1.25 daniel 4753: * xmlNodeDump:
1.42 daniel 4754: * @buf: the XML buffer output
1.23 daniel 4755: * @doc: the document
4756: * @cur: the current node
4757: * @level: the imbrication level for indenting
1.64 daniel 4758: * @format: is formatting allowed
1.23 daniel 4759: *
4760: * Dump an XML node, recursive behaviour,children are printed too.
1.1 veillard 4761: */
1.125 veillard 4762: void
1.64 daniel 4763: xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
4764: int format) {
1.8 veillard 4765: int i;
1.64 daniel 4766: xmlNodePtr tmp;
1.8 veillard 4767:
1.1 veillard 4768: if (cur == NULL) {
1.86 daniel 4769: #ifdef DEBUG_TREE
1.8 veillard 4770: fprintf(stderr, "xmlNodeDump : node == NULL\n");
1.86 daniel 4771: #endif
1.8 veillard 4772: return;
4773: }
1.92 daniel 4774: if (cur->type == XML_DTD_NODE) {
4775: xmlDtdDump(buf, (xmlDtdPtr) cur);
4776: return;
4777: }
1.99 daniel 4778: if (cur->type == XML_ELEMENT_DECL) {
4779: xmlDumpElementDecl(buf, (xmlElementPtr) cur);
4780: return;
4781: }
4782: if (cur->type == XML_ATTRIBUTE_DECL) {
4783: xmlDumpAttributeDecl(buf, (xmlAttributePtr) cur);
4784: return;
4785: }
4786: if (cur->type == XML_ENTITY_DECL) {
4787: xmlDumpEntityDecl(buf, (xmlEntityPtr) cur);
4788: return;
4789: }
1.23 daniel 4790: if (cur->type == XML_TEXT_NODE) {
1.45 daniel 4791: if (cur->content != NULL) {
1.61 daniel 4792: xmlChar *buffer;
1.45 daniel 4793:
1.70 daniel 4794: #ifndef XML_USE_BUFFER_CONTENT
1.46 daniel 4795: buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
1.70 daniel 4796: #else
4797: buffer = xmlEncodeEntitiesReentrant(doc,
4798: xmlBufferContent(cur->content));
4799: #endif
1.45 daniel 4800: if (buffer != NULL) {
4801: xmlBufferWriteCHAR(buf, buffer);
1.57 daniel 4802: xmlFree(buffer);
1.45 daniel 4803: }
4804: }
1.14 daniel 4805: return;
4806: }
1.52 daniel 4807: if (cur->type == XML_PI_NODE) {
4808: if (cur->content != NULL) {
4809: xmlBufferWriteChar(buf, "<?");
4810: xmlBufferWriteCHAR(buf, cur->name);
4811: if (cur->content != NULL) {
4812: xmlBufferWriteChar(buf, " ");
1.70 daniel 4813: #ifndef XML_USE_BUFFER_CONTENT
1.52 daniel 4814: xmlBufferWriteCHAR(buf, cur->content);
1.70 daniel 4815: #else
4816: xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4817: #endif
1.52 daniel 4818: }
1.89 daniel 4819: xmlBufferWriteChar(buf, "?>");
4820: } else {
4821: xmlBufferWriteChar(buf, "<?");
4822: xmlBufferWriteCHAR(buf, cur->name);
1.64 daniel 4823: xmlBufferWriteChar(buf, "?>");
1.52 daniel 4824: }
4825: return;
4826: }
1.23 daniel 4827: if (cur->type == XML_COMMENT_NODE) {
1.14 daniel 4828: if (cur->content != NULL) {
1.38 daniel 4829: xmlBufferWriteChar(buf, "<!--");
1.70 daniel 4830: #ifndef XML_USE_BUFFER_CONTENT
1.38 daniel 4831: xmlBufferWriteCHAR(buf, cur->content);
1.70 daniel 4832: #else
4833: xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4834: #endif
1.64 daniel 4835: xmlBufferWriteChar(buf, "-->");
1.14 daniel 4836: }
1.8 veillard 4837: return;
4838: }
1.23 daniel 4839: if (cur->type == XML_ENTITY_REF_NODE) {
1.38 daniel 4840: xmlBufferWriteChar(buf, "&");
4841: xmlBufferWriteCHAR(buf, cur->name);
4842: xmlBufferWriteChar(buf, ";");
1.50 daniel 4843: return;
4844: }
4845: if (cur->type == XML_CDATA_SECTION_NODE) {
4846: xmlBufferWriteChar(buf, "<![CDATA[");
4847: if (cur->content != NULL)
1.70 daniel 4848: #ifndef XML_USE_BUFFER_CONTENT
1.50 daniel 4849: xmlBufferWriteCHAR(buf, cur->content);
1.70 daniel 4850: #else
4851: xmlBufferWriteCHAR(buf, xmlBufferContent(cur->content));
4852: #endif
1.50 daniel 4853: xmlBufferWriteChar(buf, "]]>");
1.23 daniel 4854: return;
4855: }
1.8 veillard 4856:
1.64 daniel 4857: if (format == 1) {
1.91 daniel 4858: tmp = cur->children;
1.64 daniel 4859: while (tmp != NULL) {
4860: if ((tmp->type == XML_TEXT_NODE) ||
4861: (tmp->type == XML_ENTITY_REF_NODE)) {
4862: format = 0;
4863: break;
4864: }
4865: tmp = tmp->next;
4866: }
4867: }
1.38 daniel 4868: xmlBufferWriteChar(buf, "<");
1.16 daniel 4869: if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1.38 daniel 4870: xmlBufferWriteCHAR(buf, cur->ns->prefix);
4871: xmlBufferWriteChar(buf, ":");
1.8 veillard 4872: }
4873:
1.38 daniel 4874: xmlBufferWriteCHAR(buf, cur->name);
1.19 daniel 4875: if (cur->nsDef)
1.38 daniel 4876: xmlNsListDump(buf, cur->nsDef);
1.8 veillard 4877: if (cur->properties != NULL)
1.38 daniel 4878: xmlAttrListDump(buf, doc, cur->properties);
1.8 veillard 4879:
1.90 daniel 4880: if ((cur->content == NULL) && (cur->children == NULL) &&
1.87 daniel 4881: (!xmlSaveNoEmptyTags)) {
1.64 daniel 4882: xmlBufferWriteChar(buf, "/>");
1.1 veillard 4883: return;
4884: }
1.38 daniel 4885: xmlBufferWriteChar(buf, ">");
1.46 daniel 4886: if (cur->content != NULL) {
1.61 daniel 4887: xmlChar *buffer;
1.46 daniel 4888:
1.70 daniel 4889: #ifndef XML_USE_BUFFER_CONTENT
1.46 daniel 4890: buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
1.70 daniel 4891: #else
4892: buffer = xmlEncodeEntitiesReentrant(doc,
4893: xmlBufferContent(cur->content));
4894: #endif
1.46 daniel 4895: if (buffer != NULL) {
4896: xmlBufferWriteCHAR(buf, buffer);
1.57 daniel 4897: xmlFree(buffer);
1.46 daniel 4898: }
4899: }
1.90 daniel 4900: if (cur->children != NULL) {
1.64 daniel 4901: if (format) xmlBufferWriteChar(buf, "\n");
1.99 daniel 4902: xmlNodeListDump(buf, doc, cur->children,
4903: (level >= 0?level+1:-1), format);
1.64 daniel 4904: if ((xmlIndentTreeOutput) && (format))
4905: for (i = 0;i < level;i++)
4906: xmlBufferWriteChar(buf, " ");
1.8 veillard 4907: }
1.38 daniel 4908: xmlBufferWriteChar(buf, "</");
1.16 daniel 4909: if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1.38 daniel 4910: xmlBufferWriteCHAR(buf, cur->ns->prefix);
4911: xmlBufferWriteChar(buf, ":");
1.1 veillard 4912: }
1.8 veillard 4913:
1.38 daniel 4914: xmlBufferWriteCHAR(buf, cur->name);
1.64 daniel 4915: xmlBufferWriteChar(buf, ">");
1.1 veillard 4916: }
4917:
1.23 daniel 4918: /**
1.82 daniel 4919: * xmlElemDump:
1.104 daniel 4920: * @f: the FILE * for the output
1.82 daniel 4921: * @doc: the document
4922: * @cur: the current node
4923: *
4924: * Dump an XML/HTML node, recursive behaviour,children are printed too.
4925: */
4926: void
4927: xmlElemDump(FILE *f, xmlDocPtr doc, xmlNodePtr cur) {
4928: xmlBufferPtr buf;
4929:
4930: if (cur == NULL) {
4931: #ifdef DEBUG_TREE
4932: fprintf(stderr, "xmlElemDump : cur == NULL\n");
4933: #endif
4934: return;
4935: }
4936: if (doc == NULL) {
4937: #ifdef DEBUG_TREE
4938: fprintf(stderr, "xmlElemDump : doc == NULL\n");
4939: #endif
4940: }
4941: buf = xmlBufferCreate();
4942: if (buf == NULL) return;
4943: if ((doc != NULL) &&
4944: (doc->type == XML_HTML_DOCUMENT_NODE)) {
1.101 daniel 4945: #ifdef LIBXML_HTML_ENABLED
1.82 daniel 4946: htmlNodeDump(buf, doc, cur);
1.101 daniel 4947: #else
4948: printf("HTML support not compiled in\n");
4949: #endif /* LIBXML_HTML_ENABLED */
1.82 daniel 4950: } else
4951: xmlNodeDump(buf, doc, cur, 0, 1);
4952: xmlBufferDump(f, buf);
4953: xmlBufferFree(buf);
4954: }
4955:
4956: /**
1.23 daniel 4957: * xmlDocContentDump:
1.42 daniel 4958: * @buf: the XML buffer output
1.23 daniel 4959: * @cur: the document
4960: *
4961: * Dump an XML document.
1.1 veillard 4962: */
1.28 daniel 4963: static void
1.38 daniel 4964: xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
1.46 daniel 4965: xmlBufferWriteChar(buf, "<?xml version=");
4966: if (cur->version != NULL)
4967: xmlBufferWriteQuotedString(buf, cur->version);
4968: else
4969: xmlBufferWriteChar(buf, "\"1.0\"");
1.15 daniel 4970: if (cur->encoding != NULL) {
1.43 daniel 4971: xmlBufferWriteChar(buf, " encoding=");
4972: xmlBufferWriteQuotedString(buf, cur->encoding);
1.15 daniel 4973: }
4974: switch (cur->standalone) {
4975: case 0:
1.38 daniel 4976: xmlBufferWriteChar(buf, " standalone=\"no\"");
1.15 daniel 4977: break;
4978: case 1:
1.38 daniel 4979: xmlBufferWriteChar(buf, " standalone=\"yes\"");
1.15 daniel 4980: break;
4981: }
1.38 daniel 4982: xmlBufferWriteChar(buf, "?>\n");
1.90 daniel 4983: if (cur->children != NULL) {
4984: xmlNodePtr child = cur->children;
1.52 daniel 4985:
1.19 daniel 4986: /* global namespace definitions, the old way */
4987: if (oldXMLWDcompatibility)
1.38 daniel 4988: xmlGlobalNsListDump(buf, cur->oldNs);
1.19 daniel 4989: else
4990: xmlUpgradeOldNs(cur);
1.52 daniel 4991:
4992: while (child != NULL) {
1.64 daniel 4993: xmlNodeDump(buf, cur, child, 0, 1);
4994: xmlBufferWriteChar(buf, "\n");
1.52 daniel 4995: child = child->next;
4996: }
1.19 daniel 4997: }
4998: }
4999:
1.106 daniel 5000: /************************************************************************
5001: * *
5002: * Dumping XML tree content to an I/O output buffer *
5003: * *
5004: ************************************************************************/
5005:
1.125 veillard 5006: void
1.106 daniel 5007: xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
1.108 daniel 5008: int level, int format, const char *encoding);
1.106 daniel 5009: static void
5010: xmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
1.108 daniel 5011: int level, int format, const char *encoding);
1.106 daniel 5012: /**
5013: * xmlGlobalNsDumpOutput:
5014: * @buf: the XML buffer output
5015: * @cur: a namespace
5016: *
5017: * Dump a global Namespace, this is the old version based on PIs.
5018: */
5019: static void
5020: xmlGlobalNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
5021: if (cur == NULL) {
5022: #ifdef DEBUG_TREE
5023: fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
5024: #endif
5025: return;
5026: }
5027: if (cur->type == XML_GLOBAL_NAMESPACE) {
5028: xmlOutputBufferWriteString(buf, "<?namespace");
5029: if (cur->href != NULL) {
5030: xmlOutputBufferWriteString(buf, " href=");
5031: xmlBufferWriteQuotedString(buf->buffer, cur->href);
5032: }
5033: if (cur->prefix != NULL) {
5034: xmlOutputBufferWriteString(buf, " AS=");
5035: xmlBufferWriteQuotedString(buf->buffer, cur->prefix);
5036: }
5037: xmlOutputBufferWriteString(buf, "?>\n");
5038: }
5039: }
5040:
5041: /**
5042: * xmlGlobalNsListDumpOutput:
5043: * @buf: the XML buffer output
5044: * @cur: the first namespace
5045: *
5046: * Dump a list of global Namespace, this is the old version based on PIs.
5047: */
5048: static void
5049: xmlGlobalNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
5050: while (cur != NULL) {
5051: xmlGlobalNsDumpOutput(buf, cur);
5052: cur = cur->next;
5053: }
5054: }
5055:
5056: /**
5057: * xmlNsDumpOutput:
5058: * @buf: the XML buffer output
5059: * @cur: a namespace
5060: *
5061: * Dump a local Namespace definition.
5062: * Should be called in the context of attributes dumps.
5063: */
5064: static void
5065: xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
5066: if (cur == NULL) {
5067: #ifdef DEBUG_TREE
5068: fprintf(stderr, "xmlNsDump : Ns == NULL\n");
5069: #endif
5070: return;
5071: }
1.120 veillard 5072: if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) {
1.106 daniel 5073: /* Within the context of an element attributes */
5074: if (cur->prefix != NULL) {
5075: xmlOutputBufferWriteString(buf, " xmlns:");
5076: xmlOutputBufferWriteString(buf, (const char *)cur->prefix);
5077: } else
5078: xmlOutputBufferWriteString(buf, " xmlns");
5079: xmlOutputBufferWriteString(buf, "=");
5080: xmlBufferWriteQuotedString(buf->buffer, cur->href);
5081: }
5082: }
5083:
5084: /**
5085: * xmlNsListDumpOutput:
5086: * @buf: the XML buffer output
5087: * @cur: the first namespace
5088: *
5089: * Dump a list of local Namespace definitions.
5090: * Should be called in the context of attributes dumps.
5091: */
5092: static void
5093: xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
5094: while (cur != NULL) {
5095: xmlNsDumpOutput(buf, cur);
5096: cur = cur->next;
5097: }
5098: }
5099:
5100: /**
5101: * xmlDtdDumpOutput:
5102: * @buf: the XML buffer output
5103: * @doc: the document
1.108 daniel 5104: * @encoding: an optional encoding string
1.106 daniel 5105: *
5106: * Dump the XML document DTD, if any.
5107: */
5108: static void
1.108 daniel 5109: xmlDtdDumpOutput(xmlOutputBufferPtr buf, xmlDtdPtr dtd, const char *encoding) {
1.106 daniel 5110: if (dtd == NULL) {
5111: #ifdef DEBUG_TREE
5112: fprintf(stderr, "xmlDtdDump : no internal subset\n");
5113: #endif
5114: return;
5115: }
5116: xmlOutputBufferWriteString(buf, "<!DOCTYPE ");
5117: xmlOutputBufferWriteString(buf, (const char *)dtd->name);
5118: if (dtd->ExternalID != NULL) {
5119: xmlOutputBufferWriteString(buf, " PUBLIC ");
5120: xmlBufferWriteQuotedString(buf->buffer, dtd->ExternalID);
5121: xmlOutputBufferWriteString(buf, " ");
5122: xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
5123: } else if (dtd->SystemID != NULL) {
5124: xmlOutputBufferWriteString(buf, " SYSTEM ");
5125: xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
5126: }
5127: if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
5128: (dtd->attributes == NULL) && (dtd->notations == NULL)) {
5129: xmlOutputBufferWriteString(buf, ">");
5130: return;
5131: }
5132: xmlOutputBufferWriteString(buf, " [\n");
1.108 daniel 5133: xmlNodeListDumpOutput(buf, dtd->doc, dtd->children, -1, 0, encoding);
1.106 daniel 5134: #if 0
5135: if (dtd->entities != NULL)
5136: xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) dtd->entities);
5137: if (dtd->notations != NULL)
5138: xmlDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations);
5139: if (dtd->elements != NULL)
5140: xmlDumpElementTable(buf, (xmlElementTablePtr) dtd->elements);
5141: if (dtd->attributes != NULL)
5142: xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) dtd->attributes);
5143: #endif
5144: xmlOutputBufferWriteString(buf, "]>");
5145: }
5146:
5147: /**
5148: * xmlAttrDumpOutput:
5149: * @buf: the XML buffer output
5150: * @doc: the document
5151: * @cur: the attribute pointer
1.108 daniel 5152: * @encoding: an optional encoding string
1.106 daniel 5153: *
5154: * Dump an XML attribute
5155: */
5156: static void
1.108 daniel 5157: xmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur,
5158: const char *encoding) {
1.106 daniel 5159: xmlChar *value;
5160:
5161: if (cur == NULL) {
5162: #ifdef DEBUG_TREE
5163: fprintf(stderr, "xmlAttrDump : property == NULL\n");
5164: #endif
5165: return;
5166: }
5167: xmlOutputBufferWriteString(buf, " ");
5168: if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5169: xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
5170: xmlOutputBufferWriteString(buf, ":");
5171: }
5172: xmlOutputBufferWriteString(buf, (const char *)cur->name);
5173: value = xmlNodeListGetString(doc, cur->children, 0);
5174: if (value) {
5175: xmlOutputBufferWriteString(buf, "=");
5176: xmlBufferWriteQuotedString(buf->buffer, value);
5177: xmlFree(value);
5178: } else {
5179: xmlOutputBufferWriteString(buf, "=\"\"");
5180: }
5181: }
5182:
5183: /**
5184: * xmlAttrListDumpOutput:
5185: * @buf: the XML buffer output
5186: * @doc: the document
5187: * @cur: the first attribute pointer
1.108 daniel 5188: * @encoding: an optional encoding string
1.106 daniel 5189: *
5190: * Dump a list of XML attributes
5191: */
5192: static void
1.108 daniel 5193: xmlAttrListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
5194: xmlAttrPtr cur, const char *encoding) {
1.106 daniel 5195: if (cur == NULL) {
5196: #ifdef DEBUG_TREE
5197: fprintf(stderr, "xmlAttrListDump : property == NULL\n");
5198: #endif
5199: return;
5200: }
5201: while (cur != NULL) {
1.108 daniel 5202: xmlAttrDumpOutput(buf, doc, cur, encoding);
1.106 daniel 5203: cur = cur->next;
5204: }
5205: }
5206:
5207:
5208:
5209: /**
5210: * xmlNodeListDumpOutput:
5211: * @buf: the XML buffer output
5212: * @doc: the document
5213: * @cur: the first node
5214: * @level: the imbrication level for indenting
5215: * @format: is formatting allowed
1.108 daniel 5216: * @encoding: an optional encoding string
1.106 daniel 5217: *
5218: * Dump an XML node list, recursive behaviour,children are printed too.
5219: */
5220: static void
5221: xmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
1.108 daniel 5222: xmlNodePtr cur, int level, int format, const char *encoding) {
1.106 daniel 5223: int i;
5224:
5225: if (cur == NULL) {
5226: #ifdef DEBUG_TREE
5227: fprintf(stderr, "xmlNodeListDump : node == NULL\n");
5228: #endif
5229: return;
5230: }
5231: while (cur != NULL) {
5232: if ((format) && (xmlIndentTreeOutput) &&
5233: (cur->type == XML_ELEMENT_NODE))
5234: for (i = 0;i < level;i++)
5235: xmlOutputBufferWriteString(buf, " ");
1.108 daniel 5236: xmlNodeDumpOutput(buf, doc, cur, level, format, encoding);
1.106 daniel 5237: if (format) {
5238: xmlOutputBufferWriteString(buf, "\n");
5239: }
5240: cur = cur->next;
5241: }
5242: }
5243:
5244: /**
5245: * xmlNodeDumpOutput:
5246: * @buf: the XML buffer output
5247: * @doc: the document
5248: * @cur: the current node
5249: * @level: the imbrication level for indenting
5250: * @format: is formatting allowed
1.108 daniel 5251: * @encoding: an optional encoding string
1.106 daniel 5252: *
5253: * Dump an XML node, recursive behaviour,children are printed too.
5254: */
1.125 veillard 5255: void
1.106 daniel 5256: xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
1.108 daniel 5257: int level, int format, const char *encoding) {
1.106 daniel 5258: int i;
5259: xmlNodePtr tmp;
5260:
5261: if (cur == NULL) {
5262: #ifdef DEBUG_TREE
5263: fprintf(stderr, "xmlNodeDump : node == NULL\n");
5264: #endif
5265: return;
5266: }
5267: if (cur->type == XML_DTD_NODE) {
1.108 daniel 5268: xmlDtdDumpOutput(buf, (xmlDtdPtr) cur, encoding);
1.106 daniel 5269: return;
5270: }
5271: if (cur->type == XML_ELEMENT_DECL) {
5272: xmlDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
5273: return;
5274: }
5275: if (cur->type == XML_ATTRIBUTE_DECL) {
5276: xmlDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
5277: return;
5278: }
5279: if (cur->type == XML_ENTITY_DECL) {
5280: xmlDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
5281: return;
5282: }
5283: if (cur->type == XML_TEXT_NODE) {
5284: if (cur->content != NULL) {
5285: xmlChar *buffer;
5286:
5287: #ifndef XML_USE_BUFFER_CONTENT
1.108 daniel 5288: if (encoding == NULL)
5289: buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
5290: else
5291: buffer = xmlEncodeSpecialChars(doc, cur->content);
1.106 daniel 5292: #else
1.108 daniel 5293: if (encoding == NULL)
5294: buffer = xmlEncodeEntitiesReentrant(doc,
5295: xmlBufferContent(cur->content));
5296: else
5297: buffer = xmlEncodeSpecialChars(doc,
5298: xmlBufferContent(cur->content));
1.106 daniel 5299: #endif
5300: if (buffer != NULL) {
5301: xmlOutputBufferWriteString(buf, (const char *)buffer);
5302: xmlFree(buffer);
5303: }
5304: }
5305: return;
5306: }
5307: if (cur->type == XML_PI_NODE) {
5308: if (cur->content != NULL) {
5309: xmlOutputBufferWriteString(buf, "<?");
5310: xmlOutputBufferWriteString(buf, (const char *)cur->name);
5311: if (cur->content != NULL) {
5312: xmlOutputBufferWriteString(buf, " ");
5313: #ifndef XML_USE_BUFFER_CONTENT
5314: xmlOutputBufferWriteString(buf, (const char *)cur->content);
5315: #else
5316: xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
5317: #endif
5318: }
5319: xmlOutputBufferWriteString(buf, "?>");
5320: } else {
5321: xmlOutputBufferWriteString(buf, "<?");
5322: xmlOutputBufferWriteString(buf, (const char *)cur->name);
5323: xmlOutputBufferWriteString(buf, "?>");
5324: }
5325: return;
5326: }
5327: if (cur->type == XML_COMMENT_NODE) {
5328: if (cur->content != NULL) {
5329: xmlOutputBufferWriteString(buf, "<!--");
5330: #ifndef XML_USE_BUFFER_CONTENT
5331: xmlOutputBufferWriteString(buf, (const char *)cur->content);
5332: #else
5333: xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
5334: #endif
5335: xmlOutputBufferWriteString(buf, "-->");
5336: }
5337: return;
5338: }
5339: if (cur->type == XML_ENTITY_REF_NODE) {
5340: xmlOutputBufferWriteString(buf, "&");
5341: xmlOutputBufferWriteString(buf, (const char *)cur->name);
5342: xmlOutputBufferWriteString(buf, ";");
5343: return;
5344: }
5345: if (cur->type == XML_CDATA_SECTION_NODE) {
5346: xmlOutputBufferWriteString(buf, "<![CDATA[");
5347: if (cur->content != NULL)
5348: #ifndef XML_USE_BUFFER_CONTENT
5349: xmlOutputBufferWriteString(buf, (const char *)cur->content);
5350: #else
5351: xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
5352: #endif
5353: xmlOutputBufferWriteString(buf, "]]>");
5354: return;
5355: }
5356:
5357: if (format == 1) {
5358: tmp = cur->children;
5359: while (tmp != NULL) {
5360: if ((tmp->type == XML_TEXT_NODE) ||
5361: (tmp->type == XML_ENTITY_REF_NODE)) {
5362: format = 0;
5363: break;
5364: }
5365: tmp = tmp->next;
5366: }
5367: }
5368: xmlOutputBufferWriteString(buf, "<");
5369: if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5370: xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
5371: xmlOutputBufferWriteString(buf, ":");
5372: }
5373:
5374: xmlOutputBufferWriteString(buf, (const char *)cur->name);
5375: if (cur->nsDef)
5376: xmlNsListDumpOutput(buf, cur->nsDef);
5377: if (cur->properties != NULL)
1.108 daniel 5378: xmlAttrListDumpOutput(buf, doc, cur->properties, encoding);
1.106 daniel 5379:
5380: if ((cur->content == NULL) && (cur->children == NULL) &&
5381: (!xmlSaveNoEmptyTags)) {
5382: xmlOutputBufferWriteString(buf, "/>");
5383: return;
5384: }
5385: xmlOutputBufferWriteString(buf, ">");
5386: if (cur->content != NULL) {
5387: xmlChar *buffer;
5388:
5389: #ifndef XML_USE_BUFFER_CONTENT
1.108 daniel 5390: if (encoding == NULL)
5391: buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
5392: else
5393: buffer = xmlEncodeSpecialChars(doc, cur->content);
1.106 daniel 5394: #else
1.108 daniel 5395: if (encoding == NULL)
5396: buffer = xmlEncodeEntitiesReentrant(doc,
5397: xmlBufferContent(cur->content));
5398: else
5399: buffer = xmlEncodeSpecialChars(doc,
5400: xmlBufferContent(cur->content));
1.106 daniel 5401: #endif
5402: if (buffer != NULL) {
5403: xmlOutputBufferWriteString(buf, (const char *)buffer);
5404: xmlFree(buffer);
5405: }
5406: }
5407: if (cur->children != NULL) {
5408: if (format) xmlOutputBufferWriteString(buf, "\n");
5409: xmlNodeListDumpOutput(buf, doc, cur->children,
1.108 daniel 5410: (level >= 0?level+1:-1), format, encoding);
1.106 daniel 5411: if ((xmlIndentTreeOutput) && (format))
5412: for (i = 0;i < level;i++)
5413: xmlOutputBufferWriteString(buf, " ");
5414: }
5415: xmlOutputBufferWriteString(buf, "</");
5416: if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
5417: xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
5418: xmlOutputBufferWriteString(buf, ":");
5419: }
5420:
5421: xmlOutputBufferWriteString(buf, (const char *)cur->name);
5422: xmlOutputBufferWriteString(buf, ">");
5423: }
5424:
5425: /**
5426: * xmlDocContentDumpOutput:
5427: * @buf: the XML buffer output
5428: * @cur: the document
1.107 daniel 5429: * @encoding: an optional encoding string
1.106 daniel 5430: *
5431: * Dump an XML document.
5432: */
5433: static void
1.107 daniel 5434: xmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
5435: const char *encoding) {
1.106 daniel 5436: xmlOutputBufferWriteString(buf, "<?xml version=");
5437: if (cur->version != NULL)
5438: xmlBufferWriteQuotedString(buf->buffer, cur->version);
5439: else
5440: xmlOutputBufferWriteString(buf, "\"1.0\"");
1.109 daniel 5441: if (encoding == NULL) {
5442: if (cur->encoding != NULL)
5443: encoding = (const char *) cur->encoding;
5444: else if (cur->charset != XML_CHAR_ENCODING_UTF8)
1.112 veillard 5445: encoding = xmlGetCharEncodingName((xmlCharEncoding) cur->charset);
1.109 daniel 5446: }
1.107 daniel 5447: if (encoding != NULL) {
1.106 daniel 5448: xmlOutputBufferWriteString(buf, " encoding=");
1.107 daniel 5449: xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
1.106 daniel 5450: }
5451: switch (cur->standalone) {
5452: case 0:
5453: xmlOutputBufferWriteString(buf, " standalone=\"no\"");
5454: break;
5455: case 1:
5456: xmlOutputBufferWriteString(buf, " standalone=\"yes\"");
5457: break;
5458: }
5459: xmlOutputBufferWriteString(buf, "?>\n");
5460: if (cur->children != NULL) {
5461: xmlNodePtr child = cur->children;
5462:
5463: /* global namespace definitions, the old way */
5464: if (oldXMLWDcompatibility)
5465: xmlGlobalNsListDumpOutput(buf, cur->oldNs);
5466: else
5467: xmlUpgradeOldNs(cur);
5468:
5469: while (child != NULL) {
1.108 daniel 5470: xmlNodeDumpOutput(buf, cur, child, 0, 1, encoding);
1.106 daniel 5471: xmlOutputBufferWriteString(buf, "\n");
5472: child = child->next;
5473: }
5474: }
5475: }
5476:
5477: /************************************************************************
5478: * *
5479: * Saving functions front-ends *
5480: * *
5481: ************************************************************************/
5482:
1.23 daniel 5483: /**
5484: * xmlDocDumpMemory:
5485: * @cur: the document
5486: * @mem: OUT: the memory pointer
5487: * @size: OUT: the memory lenght
5488: *
1.61 daniel 5489: * Dump an XML document in memory and return the xmlChar * and it's size.
1.23 daniel 5490: * It's up to the caller to free the memory.
1.19 daniel 5491: */
1.28 daniel 5492: void
1.61 daniel 5493: xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
1.38 daniel 5494: xmlBufferPtr buf;
5495:
1.19 daniel 5496: if (cur == NULL) {
1.31 daniel 5497: #ifdef DEBUG_TREE
5498: fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
5499: #endif
1.19 daniel 5500: *mem = NULL;
5501: *size = 0;
5502: return;
5503: }
1.38 daniel 5504: buf = xmlBufferCreate();
5505: if (buf == NULL) {
5506: *mem = NULL;
5507: *size = 0;
5508: return;
5509: }
5510: xmlDocContentDump(buf, cur);
1.51 daniel 5511: *mem = xmlStrndup(buf->content, buf->use);
1.38 daniel 5512: *size = buf->use;
1.51 daniel 5513: xmlBufferFree(buf);
1.1 veillard 5514: }
5515:
1.23 daniel 5516: /**
5517: * xmlGetDocCompressMode:
5518: * @doc: the document
5519: *
5520: * get the compression ratio for a document, ZLIB based
1.36 daniel 5521: * Returns 0 (uncompressed) to 9 (max compression)
1.23 daniel 5522: */
1.28 daniel 5523: int
1.82 daniel 5524: xmlGetDocCompressMode (xmlDocPtr doc) {
1.23 daniel 5525: if (doc == NULL) return(-1);
5526: return(doc->compression);
5527: }
5528:
5529: /**
5530: * xmlSetDocCompressMode:
5531: * @doc: the document
5532: * @mode: the compression ratio
5533: *
5534: * set the compression ratio for a document, ZLIB based
5535: * Correct values: 0 (uncompressed) to 9 (max compression)
5536: */
1.28 daniel 5537: void
5538: xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
1.23 daniel 5539: if (doc == NULL) return;
5540: if (mode < 0) doc->compression = 0;
5541: else if (mode > 9) doc->compression = 9;
5542: else doc->compression = mode;
5543: }
5544:
5545: /**
5546: * xmlGetCompressMode:
5547: *
5548: * get the default compression mode used, ZLIB based.
1.36 daniel 5549: * Returns 0 (uncompressed) to 9 (max compression)
1.23 daniel 5550: */
1.28 daniel 5551: int
5552: xmlGetCompressMode(void) {
1.23 daniel 5553: return(xmlCompressMode);
5554: }
5555:
5556: /**
5557: * xmlSetCompressMode:
5558: * @mode: the compression ratio
5559: *
5560: * set the default compression mode used, ZLIB based
5561: * Correct values: 0 (uncompressed) to 9 (max compression)
1.1 veillard 5562: */
1.28 daniel 5563: void
5564: xmlSetCompressMode(int mode) {
1.23 daniel 5565: if (mode < 0) xmlCompressMode = 0;
5566: else if (mode > 9) xmlCompressMode = 9;
5567: else xmlCompressMode = mode;
5568: }
1.1 veillard 5569:
1.106 daniel 5570: /**
5571: * xmlDocDump:
5572: * @f: the FILE*
5573: * @cur: the document
5574: *
5575: * Dump an XML document to an open FILE.
5576: *
1.111 veillard 5577: * returns: the number of byte written or -1 in case of failure.
1.106 daniel 5578: */
5579: int
5580: xmlDocDump(FILE *f, xmlDocPtr cur) {
5581: xmlOutputBufferPtr buf;
1.114 veillard 5582: const char * encoding;
5583: xmlCharEncodingHandlerPtr handler = NULL;
1.106 daniel 5584: int ret;
5585:
5586: if (cur == NULL) {
5587: #ifdef DEBUG_TREE
5588: fprintf(stderr, "xmlDocDump : document == NULL\n");
5589: #endif
5590: return(-1);
5591: }
1.114 veillard 5592: encoding = (const char *) cur->encoding;
1.106 daniel 5593:
1.114 veillard 5594: if (encoding != NULL) {
5595: xmlCharEncoding enc;
1.106 daniel 5596:
1.114 veillard 5597: enc = xmlParseCharEncoding(encoding);
1.106 daniel 5598:
1.114 veillard 5599: if (cur->charset != XML_CHAR_ENCODING_UTF8) {
5600: fprintf(stderr, "xmlDocDump: document not in UTF8\n");
5601: return(-1);
5602: }
1.115 veillard 5603: if (enc != XML_CHAR_ENCODING_UTF8) {
5604: handler = xmlFindCharEncodingHandler(encoding);
5605: if (handler == NULL) {
5606: xmlFree((char *) cur->encoding);
5607: cur->encoding = NULL;
5608: }
1.114 veillard 5609: }
5610: }
5611: buf = xmlOutputBufferCreateFile(f, handler);
5612: if (buf == NULL) return(-1);
1.107 daniel 5613: xmlDocContentDumpOutput(buf, cur, NULL);
1.106 daniel 5614:
5615: ret = xmlOutputBufferClose(buf);
5616: return(ret);
5617: }
1.1 veillard 5618:
1.106 daniel 5619: /**
5620: * xmlSaveFileTo:
5621: * @buf: an output I/O buffer
5622: * @cur: the document
1.107 daniel 5623: * @encoding: the encoding if any assuming the i/O layer handles the trancoding
1.106 daniel 5624: *
5625: * Dump an XML document to an I/O buffer.
5626: *
1.111 veillard 5627: * returns: the number of byte written or -1 in case of failure.
1.106 daniel 5628: */
5629: int
1.107 daniel 5630: xmlSaveFileTo(xmlOutputBuffer *buf, xmlDocPtr cur, const char *encoding) {
1.106 daniel 5631: int ret;
5632:
5633: if (buf == NULL) return(0);
1.107 daniel 5634: xmlDocContentDumpOutput(buf, cur, encoding);
1.106 daniel 5635: ret = xmlOutputBufferClose(buf);
5636: return(ret);
5637: }
5638:
5639: /**
5640: * xmlSaveFileEnc:
5641: * @filename: the filename (or URL)
5642: * @cur: the document
5643: * @encoding: the name of an encoding (or NULL)
5644: *
5645: * Dump an XML document, converting it to the given encoding
5646: *
1.111 veillard 5647: * returns: the number of byte written or -1 in case of failure.
1.106 daniel 5648: */
5649: int
5650: xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) {
5651: xmlOutputBufferPtr buf;
5652: xmlCharEncodingHandlerPtr handler = NULL;
5653: int ret;
5654:
5655: if (encoding != NULL) {
1.110 daniel 5656: xmlCharEncoding enc;
5657:
5658: enc = xmlParseCharEncoding(encoding);
1.114 veillard 5659: if (cur->charset != XML_CHAR_ENCODING_UTF8) {
5660: fprintf(stderr, "xmlSaveFileEnc: document not in UTF8\n");
5661: return(-1);
5662: }
1.115 veillard 5663: if (enc != XML_CHAR_ENCODING_UTF8) {
5664: handler = xmlFindCharEncodingHandler(encoding);
5665: if (handler == NULL) {
5666: return(-1);
5667: }
1.110 daniel 5668: }
1.106 daniel 5669: }
5670:
5671: /*
5672: * save the content to a temp buffer.
5673: */
5674: buf = xmlOutputBufferCreateFilename(filename, handler, 0);
5675: if (buf == NULL) return(0);
5676:
1.107 daniel 5677: xmlDocContentDumpOutput(buf, cur, encoding);
1.106 daniel 5678:
5679: ret = xmlOutputBufferClose(buf);
5680: return(ret);
5681: }
1.114 veillard 5682:
5683: /**
5684: * xmlSaveFile:
5685: * @filename: the filename (or URL)
5686: * @cur: the document
5687: *
5688: * Dump an XML document to a file. Will use compression if
5689: * compiled in and enabled. If @filename is "-" the stdout file is
5690: * used.
5691: * returns: the number of byte written or -1 in case of failure.
5692: */
5693: int
5694: xmlSaveFile(const char *filename, xmlDocPtr cur) {
5695: xmlOutputBufferPtr buf;
5696: const char *encoding;
5697: xmlCharEncodingHandlerPtr handler = NULL;
5698: int ret;
5699:
5700: if (cur == NULL)
5701: return(-1);
5702: encoding = (const char *) cur->encoding;
5703:
5704: /*
5705: * save the content to a temp buffer.
5706: */
5707: #ifdef HAVE_ZLIB_H
5708: if (cur->compression < 0) cur->compression = xmlCompressMode;
1.106 daniel 5709: #endif
1.114 veillard 5710: if (encoding != NULL) {
5711: xmlCharEncoding enc;
5712:
5713: enc = xmlParseCharEncoding(encoding);
5714:
5715: if (cur->charset != XML_CHAR_ENCODING_UTF8) {
5716: fprintf(stderr, "xmlSaveFile: document not in UTF8\n");
5717: return(-1);
5718: }
1.115 veillard 5719: if (enc != XML_CHAR_ENCODING_UTF8) {
5720: handler = xmlFindCharEncodingHandler(encoding);
5721: if (handler == NULL) {
5722: xmlFree((char *) cur->encoding);
5723: cur->encoding = NULL;
5724: }
1.114 veillard 5725: }
5726: }
5727:
5728: buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
5729: if (buf == NULL) return(0);
5730:
5731: xmlDocContentDumpOutput(buf, cur, NULL);
5732:
5733: ret = xmlOutputBufferClose(buf);
5734: return(ret);
5735: }
5736:
Webmaster