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