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