Annotation of XML/tree.c, revision 1.57
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.23 daniel 9: #include "config.h"
1.1 veillard 10: #include <stdio.h>
11: #include <ctype.h>
1.23 daniel 12: #include <stdlib.h>
1.7 veillard 13: #include <string.h> /* for memset() only ! */
1.1 veillard 14:
1.23 daniel 15: #ifdef HAVE_ZLIB_H
16: #include <zlib.h>
17: #endif
18:
1.57 ! daniel 19: #include "xmlmemory.h"
1.1 veillard 20: #include "tree.h"
1.6 veillard 21: #include "entities.h"
1.33 daniel 22: #include "valid.h"
1.1 veillard 23:
1.7 veillard 24: static CHAR xmlStringText[] = { 't', 'e', 'x', 't', 0 };
1.12 daniel 25: int oldXMLWDcompatibility = 0;
1.21 daniel 26: int xmlIndentTreeOutput = 1;
1.7 veillard 27:
1.23 daniel 28: static int xmlCompressMode = 0;
29:
1.32 daniel 30: #define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \
31: xmlNodePtr ulccur = (n)->childs; \
32: if (ulccur == NULL) { \
33: (n)->last = NULL; \
34: } else { \
35: while (ulccur->next != NULL) ulccur = ulccur->next; \
36: (n)->last = ulccur; \
1.34 daniel 37: }}
1.32 daniel 38:
1.1 veillard 39: /************************************************************************
40: * *
41: * Allocation and deallocation of basic structures *
42: * *
43: ************************************************************************/
44:
1.23 daniel 45: /**
46: * xmlUpgradeOldNs:
47: * @doc: a document pointer
48: *
49: * Upgrade old style Namespaces (PI) and move them to the root of the document.
1.19 daniel 50: */
1.28 daniel 51: void
52: xmlUpgradeOldNs(xmlDocPtr doc) {
1.19 daniel 53: xmlNsPtr cur;
54:
55: if ((doc == NULL) || (doc->oldNs == NULL)) return;
56: if (doc->root == NULL) {
57: fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");
58: return;
59: }
60:
61: cur = doc->oldNs;
62: while (cur->next != NULL) {
63: cur->type = XML_LOCAL_NAMESPACE;
64: cur = cur->next;
65: }
66: cur->type = XML_LOCAL_NAMESPACE;
67: cur->next = doc->root->nsDef;
68: doc->root->nsDef = doc->oldNs;
69: doc->oldNs = NULL;
70: }
71:
1.23 daniel 72: /**
73: * xmlNewNs:
74: * @node: the element carrying the namespace
75: * @href: the URI associated
76: * @prefix: the prefix for the namespace
77: *
1.17 daniel 78: * Creation of a new Namespace.
1.36 daniel 79: * Returns returns a new namespace pointer
1.1 veillard 80: */
1.28 daniel 81: xmlNsPtr
82: xmlNewNs(xmlNodePtr node, const CHAR *href, const CHAR *prefix) {
1.16 daniel 83: xmlNsPtr cur;
1.1 veillard 84:
1.19 daniel 85: if (href == NULL) {
86: fprintf(stderr, "xmlNewNs: href == NULL !\n");
87: return(NULL);
88: }
89:
1.1 veillard 90: /*
91: * Allocate a new DTD and fill the fields.
92: */
1.57 ! daniel 93: cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
1.1 veillard 94: if (cur == NULL) {
1.16 daniel 95: fprintf(stderr, "xmlNewNs : malloc failed\n");
1.1 veillard 96: return(NULL);
97: }
98:
1.19 daniel 99: cur->type = XML_LOCAL_NAMESPACE;
100: if (href != NULL)
101: cur->href = xmlStrdup(href);
102: else
103: cur->href = NULL;
104: if (prefix != NULL)
105: cur->prefix = xmlStrdup(prefix);
106: else
107: cur->prefix = NULL;
108:
109: /*
110: * Add it at the end to preserve parsing order ...
111: */
1.1 veillard 112: cur->next = NULL;
1.19 daniel 113: if (node != NULL) {
114: if (node->nsDef == NULL) {
115: node->nsDef = cur;
116: } else {
117: xmlNsPtr prev = node->nsDef;
118:
119: while (prev->next != NULL) prev = prev->next;
120: prev->next = cur;
121: }
122: }
123:
124: return(cur);
125: }
126:
1.23 daniel 127: /**
128: * xmlNewGlobalNs:
129: * @doc: the document carrying the namespace
130: * @href: the URI associated
131: * @prefix: the prefix for the namespace
132: *
133: * Creation of a Namespace, the old way using PI and without scoping, to AVOID.
1.36 daniel 134: * Returns returns a new namespace pointer
1.19 daniel 135: */
1.28 daniel 136: xmlNsPtr
137: xmlNewGlobalNs(xmlDocPtr doc, const CHAR *href, const CHAR *prefix) {
1.19 daniel 138: xmlNsPtr cur;
139:
140: /*
141: * Allocate a new DTD and fill the fields.
142: */
1.57 ! daniel 143: cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
1.19 daniel 144: if (cur == NULL) {
1.31 daniel 145: fprintf(stderr, "xmlNewGlobalNs : malloc failed\n");
1.19 daniel 146: return(NULL);
147: }
148:
149: cur->type = XML_GLOBAL_NAMESPACE;
1.1 veillard 150: if (href != NULL)
1.7 veillard 151: cur->href = xmlStrdup(href);
1.1 veillard 152: else
153: cur->href = NULL;
1.16 daniel 154: if (prefix != NULL)
155: cur->prefix = xmlStrdup(prefix);
1.1 veillard 156: else
1.16 daniel 157: cur->prefix = NULL;
1.17 daniel 158:
159: /*
160: * Add it at the end to preserve parsing order ...
161: */
162: cur->next = NULL;
1.1 veillard 163: if (doc != NULL) {
1.19 daniel 164: if (doc->oldNs == NULL) {
165: doc->oldNs = cur;
1.17 daniel 166: } else {
1.19 daniel 167: xmlNsPtr prev = doc->oldNs;
1.17 daniel 168:
169: while (prev->next != NULL) prev = prev->next;
170: prev->next = cur;
171: }
1.1 veillard 172: }
1.3 veillard 173:
1.1 veillard 174: return(cur);
175: }
176:
1.23 daniel 177: /**
178: * xmlSetNs:
179: * @node: a node in the document
180: * @ns: a namespace pointer
181: *
182: * Associate a namespace to a node, a posteriori.
1.19 daniel 183: */
1.28 daniel 184: void
185: xmlSetNs(xmlNodePtr node, xmlNsPtr ns) {
1.19 daniel 186: if (node == NULL) {
187: fprintf(stderr, "xmlSetNs: node == NULL\n");
188: return;
189: }
190: node->ns = ns;
191: }
192:
1.23 daniel 193: /**
194: * xmlFreeNs:
195: * @cur: the namespace pointer
196: *
197: * Free up the structures associated to a namespace
1.1 veillard 198: */
1.28 daniel 199: void
200: xmlFreeNs(xmlNsPtr cur) {
1.1 veillard 201: if (cur == NULL) {
1.17 daniel 202: fprintf(stderr, "xmlFreeNs : ns == NULL\n");
1.1 veillard 203: return;
204: }
1.57 ! daniel 205: if (cur->href != NULL) xmlFree((char *) cur->href);
! 206: if (cur->prefix != NULL) xmlFree((char *) cur->prefix);
1.16 daniel 207: memset(cur, -1, sizeof(xmlNs));
1.57 ! daniel 208: xmlFree(cur);
1.1 veillard 209: }
210:
1.23 daniel 211: /**
212: * xmlFreeNsList:
213: * @cur: the first namespace pointer
214: *
215: * Free up all the structures associated to the chained namespaces.
1.6 veillard 216: */
1.28 daniel 217: void
218: xmlFreeNsList(xmlNsPtr cur) {
1.16 daniel 219: xmlNsPtr next;
1.6 veillard 220: if (cur == NULL) {
1.16 daniel 221: fprintf(stderr, "xmlFreeNsList : ns == NULL\n");
1.6 veillard 222: return;
223: }
224: while (cur != NULL) {
225: next = cur->next;
1.16 daniel 226: xmlFreeNs(cur);
1.6 veillard 227: cur = next;
228: }
229: }
230:
1.23 daniel 231: /**
232: * xmlNewDtd:
233: * @doc: the document pointer
234: * @name: the DTD name
235: * @ExternalID: the external ID
236: * @SystemID: the system ID
237: *
1.17 daniel 238: * Creation of a new DTD.
1.36 daniel 239: * Returns a pointer to the new DTD structure
1.17 daniel 240: */
1.28 daniel 241: xmlDtdPtr
242: xmlNewDtd(xmlDocPtr doc, const CHAR *name,
1.17 daniel 243: const CHAR *ExternalID, const CHAR *SystemID) {
244: xmlDtdPtr cur;
245:
1.31 daniel 246: if ((doc != NULL) && (doc->extSubset != NULL)) {
1.17 daniel 247: fprintf(stderr, "xmlNewDtd(%s): document %s already have a DTD %s\n",
1.31 daniel 248: /* !!! */ (char *) name, doc->name,
249: /* !!! */ (char *)doc->extSubset->name);
1.17 daniel 250: }
251:
252: /*
253: * Allocate a new DTD and fill the fields.
254: */
1.57 ! daniel 255: cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
1.17 daniel 256: if (cur == NULL) {
1.31 daniel 257: fprintf(stderr, "xmlNewDtd : malloc failed\n");
258: return(NULL);
259: }
260:
261: if (name != NULL)
262: cur->name = xmlStrdup(name);
263: else
264: cur->name = NULL;
265: if (ExternalID != NULL)
266: cur->ExternalID = xmlStrdup(ExternalID);
267: else
268: cur->ExternalID = NULL;
269: if (SystemID != NULL)
270: cur->SystemID = xmlStrdup(SystemID);
271: else
272: cur->SystemID = NULL;
1.35 daniel 273: cur->notations = NULL;
1.31 daniel 274: cur->elements = NULL;
1.34 daniel 275: cur->attributes = NULL;
1.31 daniel 276: cur->entities = NULL;
277: if (doc != NULL)
278: doc->extSubset = cur;
279:
280: return(cur);
281: }
282:
283: /**
284: * xmlCreateIntSubset:
285: * @doc: the document pointer
286: * @name: the DTD name
287: * @ExternalID: the external ID
288: * @SystemID: the system ID
289: *
1.36 daniel 290: * Create the internal subset of a document
291: * Returns a pointer to the new DTD structure
1.31 daniel 292: */
293: xmlDtdPtr
294: xmlCreateIntSubset(xmlDocPtr doc, const CHAR *name,
295: const CHAR *ExternalID, const CHAR *SystemID) {
296: xmlDtdPtr cur;
297:
298: if ((doc != NULL) && (doc->intSubset != NULL)) {
299: fprintf(stderr,
300: "xmlCreateIntSubset(): document %s already have an internal subset\n",
301: doc->name);
302: return(NULL);
303: }
304:
305: /*
306: * Allocate a new DTD and fill the fields.
307: */
1.57 ! daniel 308: cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd));
1.31 daniel 309: if (cur == NULL) {
310: fprintf(stderr, "xmlNewDtd : malloc failed\n");
1.17 daniel 311: return(NULL);
312: }
313:
314: if (name != NULL)
315: cur->name = xmlStrdup(name);
316: else
317: cur->name = NULL;
318: if (ExternalID != NULL)
319: cur->ExternalID = xmlStrdup(ExternalID);
320: else
321: cur->ExternalID = NULL;
322: if (SystemID != NULL)
323: cur->SystemID = xmlStrdup(SystemID);
324: else
325: cur->SystemID = NULL;
1.35 daniel 326: cur->notations = NULL;
1.17 daniel 327: cur->elements = NULL;
1.34 daniel 328: cur->attributes = NULL;
1.17 daniel 329: cur->entities = NULL;
1.31 daniel 330: if (doc != NULL)
331: doc->intSubset = cur;
1.17 daniel 332:
333: return(cur);
334: }
335:
1.23 daniel 336: /**
337: * xmlFreeDtd:
338: * @cur: the DTD structure to free up
339: *
340: * Free a DTD structure.
1.17 daniel 341: */
1.28 daniel 342: void
343: xmlFreeDtd(xmlDtdPtr cur) {
1.17 daniel 344: if (cur == NULL) {
345: fprintf(stderr, "xmlFreeDtd : DTD == NULL\n");
346: return;
347: }
1.57 ! daniel 348: if (cur->name != NULL) xmlFree((char *) cur->name);
! 349: if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
! 350: if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
1.35 daniel 351: if (cur->notations != NULL)
352: xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
1.17 daniel 353: if (cur->elements != NULL)
1.33 daniel 354: xmlFreeElementTable((xmlElementTablePtr) cur->elements);
1.34 daniel 355: if (cur->attributes != NULL)
356: xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
1.17 daniel 357: if (cur->entities != NULL)
358: xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
359: memset(cur, -1, sizeof(xmlDtd));
1.57 ! daniel 360: xmlFree(cur);
1.17 daniel 361: }
362:
1.23 daniel 363: /**
364: * xmlNewDoc:
365: * @version: CHAR string giving the version of XML "1.0"
366: *
1.36 daniel 367: * Returns a new document
1.1 veillard 368: */
1.28 daniel 369: xmlDocPtr
370: xmlNewDoc(const CHAR *version) {
1.1 veillard 371: xmlDocPtr cur;
372:
373: if (version == NULL) {
374: fprintf(stderr, "xmlNewDoc : version == NULL\n");
375: return(NULL);
376: }
377:
378: /*
379: * Allocate a new document and fill the fields.
380: */
1.57 ! daniel 381: cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
1.1 veillard 382: if (cur == NULL) {
383: fprintf(stderr, "xmlNewDoc : malloc failed\n");
384: return(NULL);
385: }
386:
1.23 daniel 387: cur->type = XML_DOCUMENT_NODE;
1.7 veillard 388: cur->version = xmlStrdup(version);
1.18 daniel 389: cur->name = NULL;
1.1 veillard 390: cur->root = NULL;
1.31 daniel 391: cur->intSubset = NULL;
392: cur->extSubset = NULL;
1.19 daniel 393: cur->oldNs = NULL;
1.15 daniel 394: cur->encoding = NULL;
395: cur->standalone = -1;
1.23 daniel 396: cur->compression = xmlCompressMode;
1.52 daniel 397: cur->ids = NULL;
1.39 daniel 398: #ifndef XML_WITHOUT_CORBA
1.23 daniel 399: cur->_private = NULL;
400: cur->vepv = NULL;
401: #endif
1.1 veillard 402: return(cur);
403: }
404:
1.23 daniel 405: /**
406: * xmlFreeDoc:
407: * @cur: pointer to the document
408: * @:
409: *
410: * Free up all the structures used by a document, tree included.
1.1 veillard 411: */
1.28 daniel 412: void
413: xmlFreeDoc(xmlDocPtr cur) {
1.1 veillard 414: if (cur == NULL) {
1.31 daniel 415: #ifdef DEBUG_TREE
1.1 veillard 416: fprintf(stderr, "xmlFreeDoc : document == NULL\n");
1.31 daniel 417: #endif
1.1 veillard 418: return;
419: }
1.57 ! daniel 420: if (cur->version != NULL) xmlFree((char *) cur->version);
! 421: if (cur->name != NULL) xmlFree((char *) cur->name);
! 422: if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
! 423: if (cur->root != NULL) xmlFreeNodeList(cur->root);
1.31 daniel 424: if (cur->intSubset != NULL) xmlFreeDtd(cur->intSubset);
425: if (cur->extSubset != NULL) xmlFreeDtd(cur->extSubset);
426: if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
1.52 daniel 427: if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
1.1 veillard 428: memset(cur, -1, sizeof(xmlDoc));
1.57 ! daniel 429: xmlFree(cur);
1.1 veillard 430: }
431:
1.23 daniel 432: /**
1.28 daniel 433: * xmlStringLenGetNodeList:
434: * @doc: the document
435: * @value: the value of the text
1.36 daniel 436: * @len: the length of the string value
1.28 daniel 437: *
438: * Parse the value string and build the node list associated. Should
439: * produce a flat tree with only TEXTs and ENTITY_REFs.
1.36 daniel 440: * Returns a pointer to the first child
1.28 daniel 441: */
442: xmlNodePtr
443: xmlStringLenGetNodeList(xmlDocPtr doc, const CHAR *value, int len) {
444: xmlNodePtr ret = NULL, last = NULL;
445: xmlNodePtr node;
446: CHAR *val;
447: const CHAR *cur = value;
448: const CHAR *q;
449: xmlEntityPtr ent;
450:
451: if (value == NULL) return(NULL);
452:
453: q = cur;
454: while ((*cur != 0) && (cur - value < len)) {
455: if (*cur == '&') {
456: /*
457: * Save the current text.
458: */
459: if (cur != q) {
460: if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
461: xmlNodeAddContentLen(last, q, cur - q);
462: } else {
463: node = xmlNewDocTextLen(doc, q, cur - q);
464: if (node == NULL) return(ret);
465: if (last == NULL)
466: last = ret = node;
467: else {
468: last->next = node;
469: node->prev = last;
470: last = node;
471: }
472: }
473: }
474: /*
475: * Read the entity string
476: */
477: cur++;
478: q = cur;
479: while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++;
480: if ((*cur == 0) || (cur - value >= len)) {
481: fprintf(stderr,
1.44 daniel 482: "xmlStringLenGetNodeList: unterminated entity %30s\n", q);
1.28 daniel 483: return(ret);
484: }
485: if (cur != q) {
486: /*
487: * Predefined entities don't generate nodes
488: */
489: val = xmlStrndup(q, cur - q);
490: ent = xmlGetDocEntity(doc, val);
491: if ((ent != NULL) &&
492: (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
493: if (last == NULL) {
494: node = xmlNewDocText(doc, ent->content);
495: last = ret = node;
496: } else
497: xmlNodeAddContent(last, ent->content);
498:
499: } else {
500: /*
501: * Create a new REFERENCE_REF node
502: */
503: node = xmlNewReference(doc, val);
1.30 daniel 504: if (node == NULL) {
1.57 ! daniel 505: if (val != NULL) xmlFree(val);
1.30 daniel 506: return(ret);
507: }
1.28 daniel 508: if (last == NULL)
509: last = ret = node;
510: else {
511: last->next = node;
512: node->prev = last;
513: last = node;
514: }
515: }
1.57 ! daniel 516: xmlFree(val);
1.28 daniel 517: }
518: cur++;
519: q = cur;
520: } else
521: cur++;
522: }
523: if (cur != q) {
524: /*
525: * Handle the last piece of text.
526: */
527: if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
528: xmlNodeAddContentLen(last, q, cur - q);
529: } else {
530: node = xmlNewDocTextLen(doc, q, cur - q);
531: if (node == NULL) return(ret);
532: if (last == NULL)
533: last = ret = node;
534: else {
535: last->next = node;
536: node->prev = last;
537: last = node;
538: }
539: }
540: }
541: return(ret);
542: }
543:
544: /**
1.24 daniel 545: * xmlStringGetNodeList:
546: * @doc: the document
1.23 daniel 547: * @value: the value of the attribute
548: *
1.24 daniel 549: * Parse the value string and build the node list associated. Should
550: * produce a flat tree with only TEXTs and ENTITY_REFs.
1.36 daniel 551: * Returns a pointer to the first child
1.23 daniel 552: */
1.28 daniel 553: xmlNodePtr
554: xmlStringGetNodeList(xmlDocPtr doc, const CHAR *value) {
1.23 daniel 555: xmlNodePtr ret = NULL, last = NULL;
556: xmlNodePtr node;
557: CHAR *val;
558: const CHAR *cur = value;
559: const CHAR *q;
1.28 daniel 560: xmlEntityPtr ent;
1.23 daniel 561:
562: if (value == NULL) return(NULL);
563:
564: q = cur;
565: while (*cur != 0) {
566: if (*cur == '&') {
1.28 daniel 567: /*
568: * Save the current text.
569: */
1.23 daniel 570: if (cur != q) {
1.28 daniel 571: if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
572: xmlNodeAddContentLen(last, q, cur - q);
573: } else {
574: node = xmlNewDocTextLen(doc, q, cur - q);
575: if (node == NULL) return(ret);
576: if (last == NULL)
577: last = ret = node;
578: else {
579: last->next = node;
580: node->prev = last;
581: last = node;
582: }
1.23 daniel 583: }
584: }
1.28 daniel 585: /*
586: * Read the entity string
587: */
1.23 daniel 588: cur++;
589: q = cur;
590: while ((*cur != 0) && (*cur != ';')) cur++;
591: if (*cur == 0) {
1.24 daniel 592: fprintf(stderr,
593: "xmlStringGetNodeList: unterminated entity %30s\n", q);
1.23 daniel 594: return(ret);
595: }
596: if (cur != q) {
1.28 daniel 597: /*
598: * Predefined entities don't generate nodes
599: */
1.23 daniel 600: val = xmlStrndup(q, cur - q);
1.28 daniel 601: ent = xmlGetDocEntity(doc, val);
602: if ((ent != NULL) &&
603: (ent->type == XML_INTERNAL_PREDEFINED_ENTITY)) {
604: if (last == NULL) {
605: node = xmlNewDocText(doc, ent->content);
606: last = ret = node;
607: } else
608: xmlNodeAddContent(last, ent->content);
609:
610: } else {
611: /*
612: * Create a new REFERENCE_REF node
613: */
614: node = xmlNewReference(doc, val);
1.30 daniel 615: if (node == NULL) {
1.57 ! daniel 616: if (val != NULL) xmlFree(val);
1.30 daniel 617: return(ret);
618: }
1.28 daniel 619: if (last == NULL)
620: last = ret = node;
621: else {
622: last->next = node;
623: node->prev = last;
624: last = node;
625: }
1.23 daniel 626: }
1.57 ! daniel 627: xmlFree(val);
1.23 daniel 628: }
629: cur++;
630: q = cur;
631: } else
632: cur++;
633: }
634: if (cur != q) {
1.28 daniel 635: /*
636: * Handle the last piece of text.
637: */
638: if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
639: xmlNodeAddContentLen(last, q, cur - q);
640: } else {
641: node = xmlNewDocTextLen(doc, q, cur - q);
642: if (node == NULL) return(ret);
643: if (last == NULL)
644: last = ret = node;
645: else {
646: last->next = node;
647: node->prev = last;
648: last = node;
649: }
1.23 daniel 650: }
651: }
652: return(ret);
653: }
654:
655: /**
1.24 daniel 656: * xmlNodeListGetString:
1.23 daniel 657: * @doc: the document
1.24 daniel 658: * @list: a Node list
1.23 daniel 659: * @inLine: should we replace entity contents or show their external form
660: *
1.24 daniel 661: * Returns the string equivalent to the text contained in the Node list
662: * made of TEXTs and ENTITY_REFs
1.36 daniel 663: * Returns a pointer to the string copy, the calller must free it.
1.23 daniel 664: */
1.28 daniel 665: CHAR *
666: xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
1.24 daniel 667: xmlNodePtr node = list;
1.23 daniel 668: CHAR *ret = NULL;
669: xmlEntityPtr ent;
670:
1.24 daniel 671: if (list == NULL) return(NULL);
1.23 daniel 672:
673: while (node != NULL) {
674: if (node->type == XML_TEXT_NODE) {
675: if (inLine)
676: ret = xmlStrcat(ret, node->content);
1.45 daniel 677: else {
678: CHAR *buffer;
679:
1.46 daniel 680: buffer = xmlEncodeEntitiesReentrant(doc, node->content);
1.45 daniel 681: if (buffer != NULL) {
682: ret = xmlStrcat(ret, buffer);
1.57 ! daniel 683: xmlFree(buffer);
1.45 daniel 684: }
685: }
1.23 daniel 686: } else if (node->type == XML_ENTITY_REF_NODE) {
687: if (inLine) {
688: ent = xmlGetDocEntity(doc, node->name);
689: if (ent != NULL)
690: ret = xmlStrcat(ret, ent->content);
691: else
692: ret = xmlStrcat(ret, node->content);
693: } else {
694: CHAR buf[2];
695: buf[0] = '&'; buf[1] = 0;
696: ret = xmlStrncat(ret, buf, 1);
697: ret = xmlStrcat(ret, node->name);
698: buf[0] = ';'; buf[1] = 0;
699: ret = xmlStrncat(ret, buf, 1);
700: }
1.24 daniel 701: }
702: #if 0
703: else {
704: fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
1.23 daniel 705: node->type);
706: }
1.24 daniel 707: #endif
1.23 daniel 708: node = node->next;
709: }
710: return(ret);
711: }
712:
713: /**
714: * xmlNewProp:
715: * @node: the holding node
716: * @name: the name of the attribute
717: * @value: the value of the attribute
718: *
719: * Create a new property carried by a node.
1.36 daniel 720: * Returns a pointer to the attribute
1.1 veillard 721: */
1.28 daniel 722: xmlAttrPtr
723: xmlNewProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
1.20 daniel 724: xmlAttrPtr cur;
1.1 veillard 725:
726: if (name == NULL) {
727: fprintf(stderr, "xmlNewProp : name == NULL\n");
728: return(NULL);
729: }
730:
731: /*
732: * Allocate a new property and fill the fields.
733: */
1.57 ! daniel 734: cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1.1 veillard 735: if (cur == NULL) {
736: fprintf(stderr, "xmlNewProp : malloc failed\n");
737: return(NULL);
738: }
739:
1.23 daniel 740: cur->type = XML_ATTRIBUTE_NODE;
1.1 veillard 741: cur->node = node;
1.56 daniel 742: cur->ns = NULL;
743: cur->name = xmlStrdup(name);
744: if (value != NULL)
745: cur->val = xmlStringGetNodeList(node->doc, value);
746: else
747: cur->val = NULL;
748: #ifndef XML_WITHOUT_CORBA
749: cur->_private = NULL;
750: cur->vepv = NULL;
751: #endif
752:
753: /*
754: * Add it at the end to preserve parsing order ...
755: */
756: cur->next = NULL;
757: if (node != NULL) {
758: if (node->properties == NULL) {
759: node->properties = cur;
760: } else {
761: xmlAttrPtr prev = node->properties;
762:
763: while (prev->next != NULL) prev = prev->next;
764: prev->next = cur;
765: }
766: }
767: return(cur);
768: }
769:
770: /**
771: * xmlNewNsProp:
772: * @node: the holding node
773: * @ns: the namespace
774: * @name: the name of the attribute
775: * @value: the value of the attribute
776: *
777: * Create a new property tagged with a namespace and carried by a node.
778: * Returns a pointer to the attribute
779: */
780: xmlAttrPtr
781: xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const CHAR *name,
782: const CHAR *value) {
783: xmlAttrPtr cur;
784:
785: if (name == NULL) {
786: fprintf(stderr, "xmlNewProp : name == NULL\n");
787: return(NULL);
788: }
789:
790: /*
791: * Allocate a new property and fill the fields.
792: */
1.57 ! daniel 793: cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1.56 daniel 794: if (cur == NULL) {
795: fprintf(stderr, "xmlNewProp : malloc failed\n");
796: return(NULL);
797: }
798:
799: cur->type = XML_ATTRIBUTE_NODE;
800: cur->node = node;
801: cur->ns = ns;
1.7 veillard 802: cur->name = xmlStrdup(name);
1.1 veillard 803: if (value != NULL)
1.24 daniel 804: cur->val = xmlStringGetNodeList(node->doc, value);
1.1 veillard 805: else
1.23 daniel 806: cur->val = NULL;
1.39 daniel 807: #ifndef XML_WITHOUT_CORBA
1.23 daniel 808: cur->_private = NULL;
809: cur->vepv = NULL;
810: #endif
1.17 daniel 811:
812: /*
813: * Add it at the end to preserve parsing order ...
814: */
815: cur->next = NULL;
1.1 veillard 816: if (node != NULL) {
1.17 daniel 817: if (node->properties == NULL) {
818: node->properties = cur;
819: } else {
1.20 daniel 820: xmlAttrPtr prev = node->properties;
1.17 daniel 821:
822: while (prev->next != NULL) prev = prev->next;
823: prev->next = cur;
824: }
825: }
1.1 veillard 826: return(cur);
827: }
828:
1.23 daniel 829: /**
830: * xmlNewDocProp:
831: * @doc: the document
832: * @name: the name of the attribute
833: * @value: the value of the attribute
834: *
835: * Create a new property carried by a document.
1.36 daniel 836: * Returns a pointer to the attribute
1.23 daniel 837: */
1.28 daniel 838: xmlAttrPtr
839: xmlNewDocProp(xmlDocPtr doc, const CHAR *name, const CHAR *value) {
1.23 daniel 840: xmlAttrPtr cur;
841:
842: if (name == NULL) {
843: fprintf(stderr, "xmlNewProp : name == NULL\n");
844: return(NULL);
845: }
846:
847: /*
848: * Allocate a new property and fill the fields.
849: */
1.57 ! daniel 850: cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
1.23 daniel 851: if (cur == NULL) {
852: fprintf(stderr, "xmlNewProp : malloc failed\n");
853: return(NULL);
854: }
855:
856: cur->type = XML_ATTRIBUTE_NODE;
857: cur->node = NULL;
858: cur->name = xmlStrdup(name);
859: if (value != NULL)
1.24 daniel 860: cur->val = xmlStringGetNodeList(doc, value);
1.23 daniel 861: else
862: cur->val = NULL;
1.39 daniel 863: #ifndef XML_WITHOUT_CORBA
1.23 daniel 864: cur->_private = NULL;
865: cur->vepv = NULL;
866: #endif
867:
868: cur->next = NULL;
869: return(cur);
870: }
871:
872: /**
873: * xmlFreePropList:
874: * @cur: the first property in the list
875: *
876: * Free a property and all its siblings, all the childs are freed too.
1.1 veillard 877: */
1.28 daniel 878: void
879: xmlFreePropList(xmlAttrPtr cur) {
1.20 daniel 880: xmlAttrPtr next;
1.1 veillard 881: if (cur == NULL) {
882: fprintf(stderr, "xmlFreePropList : property == NULL\n");
883: return;
884: }
885: while (cur != NULL) {
886: next = cur->next;
887: xmlFreeProp(cur);
888: cur = next;
889: }
890: }
891:
1.23 daniel 892: /**
893: * xmlFreeProp:
894: * @cur: the first property in the list
895: *
896: * Free one property, all the childs are freed too.
1.1 veillard 897: */
1.28 daniel 898: void
899: xmlFreeProp(xmlAttrPtr cur) {
1.1 veillard 900: if (cur == NULL) {
901: fprintf(stderr, "xmlFreeProp : property == NULL\n");
902: return;
903: }
1.57 ! daniel 904: if (cur->name != NULL) xmlFree((char *) cur->name);
1.23 daniel 905: if (cur->val != NULL) xmlFreeNodeList(cur->val);
1.20 daniel 906: memset(cur, -1, sizeof(xmlAttr));
1.57 ! daniel 907: xmlFree(cur);
1.1 veillard 908: }
909:
1.23 daniel 910: /**
1.52 daniel 911: * xmlNewPI:
912: * @name: the processing instruction name
913: * @content: the PI content
914: *
915: * Creation of a processing instruction element.
916: * Returns a pointer to the new node object.
917: */
918: xmlNodePtr
919: xmlNewPI(const CHAR *name, const CHAR *content) {
920: xmlNodePtr cur;
921:
922: if (name == NULL) {
923: fprintf(stderr, "xmlNewPI : name == NULL\n");
924: return(NULL);
925: }
926:
927: /*
928: * Allocate a new node and fill the fields.
929: */
1.57 ! daniel 930: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.52 daniel 931: if (cur == NULL) {
932: fprintf(stderr, "xmlNewPI : malloc failed\n");
933: return(NULL);
934: }
935:
936: cur->type = XML_PI_NODE;
937: cur->doc = NULL;
938: cur->parent = NULL;
939: cur->next = NULL;
940: cur->prev = NULL;
941: cur->childs = NULL;
942: cur->last = NULL;
943: cur->properties = NULL;
944: cur->name = xmlStrdup(name);
945: cur->ns = NULL;
946: cur->nsDef = NULL;
947: if (content != NULL)
948: cur->content = xmlStrdup(content);
949: else
950: cur->content = NULL;
951: #ifndef XML_WITHOUT_CORBA
952: cur->_private = NULL;
953: cur->vepv = NULL;
954: #endif
955: return(cur);
956: }
957:
958: /**
1.23 daniel 959: * xmlNewNode:
960: * @ns: namespace if any
961: * @name: the node name
962: *
963: * Creation of a new node element. @ns and @content are optionnal (NULL).
1.24 daniel 964: * If content is non NULL, a child list containing the TEXTs and
965: * ENTITY_REFs node will be created.
1.36 daniel 966: * Returns a pointer to the new node object.
1.1 veillard 967: */
1.28 daniel 968: xmlNodePtr
969: xmlNewNode(xmlNsPtr ns, const CHAR *name) {
1.1 veillard 970: xmlNodePtr cur;
971:
972: if (name == NULL) {
973: fprintf(stderr, "xmlNewNode : name == NULL\n");
974: return(NULL);
975: }
976:
977: /*
978: * Allocate a new node and fill the fields.
979: */
1.57 ! daniel 980: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.1 veillard 981: if (cur == NULL) {
982: fprintf(stderr, "xmlNewNode : malloc failed\n");
983: return(NULL);
984: }
985:
1.23 daniel 986: cur->type = XML_ELEMENT_NODE;
987: cur->doc = NULL;
1.1 veillard 988: cur->parent = NULL;
1.23 daniel 989: cur->next = NULL;
990: cur->prev = NULL;
991: cur->childs = NULL;
1.32 daniel 992: cur->last = NULL;
1.23 daniel 993: cur->properties = NULL;
1.22 daniel 994: cur->name = xmlStrdup(name);
1.16 daniel 995: cur->ns = ns;
1.19 daniel 996: cur->nsDef = NULL;
1.24 daniel 997: cur->content = NULL;
1.39 daniel 998: #ifndef XML_WITHOUT_CORBA
1.23 daniel 999: cur->_private = NULL;
1000: cur->vepv = NULL;
1001: #endif
1.1 veillard 1002: return(cur);
1003: }
1004:
1.23 daniel 1005: /**
1006: * xmlNewDocNode:
1007: * @doc: the document
1008: * @ns: namespace if any
1009: * @name: the node name
1010: * @content: the text content if any
1011: *
1012: * Creation of a new node element within a document. @ns and @content
1013: * are optionnal (NULL).
1.36 daniel 1014: * Returns a pointer to the new node object.
1.23 daniel 1015: */
1.28 daniel 1016: xmlNodePtr
1017: xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
1.48 daniel 1018: const CHAR *name, const CHAR *content) {
1.23 daniel 1019: xmlNodePtr cur;
1020:
1.24 daniel 1021: cur = xmlNewNode(ns, name);
1022: if (cur != NULL) {
1023: cur->doc = doc;
1.32 daniel 1024: if (content != NULL) {
1.24 daniel 1025: cur->childs = xmlStringGetNodeList(doc, content);
1.34 daniel 1026: UPDATE_LAST_CHILD(cur)
1.32 daniel 1027: }
1.24 daniel 1028: }
1.23 daniel 1029: return(cur);
1030: }
1031:
1032:
1033: /**
1034: * xmlNewText:
1035: * @content: the text content
1036: *
1037: * Creation of a new text node.
1.36 daniel 1038: * Returns a pointer to the new node object.
1.3 veillard 1039: */
1.28 daniel 1040: xmlNodePtr
1041: xmlNewText(const CHAR *content) {
1.3 veillard 1042: xmlNodePtr cur;
1043:
1044: /*
1045: * Allocate a new node and fill the fields.
1046: */
1.57 ! daniel 1047: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.3 veillard 1048: if (cur == NULL) {
1.19 daniel 1049: fprintf(stderr, "xmlNewText : malloc failed\n");
1.3 veillard 1050: return(NULL);
1051: }
1052:
1.23 daniel 1053: cur->type = XML_TEXT_NODE;
1054: cur->doc = NULL;
1.3 veillard 1055: cur->parent = NULL;
1056: cur->next = NULL;
1.23 daniel 1057: cur->prev = NULL;
1.3 veillard 1058: cur->childs = NULL;
1.32 daniel 1059: cur->last = NULL;
1.3 veillard 1060: cur->properties = NULL;
1.23 daniel 1061: cur->type = XML_TEXT_NODE;
1.18 daniel 1062: cur->name = xmlStrdup(xmlStringText);
1.16 daniel 1063: cur->ns = NULL;
1.19 daniel 1064: cur->nsDef = NULL;
1.3 veillard 1065: if (content != NULL)
1.7 veillard 1066: cur->content = xmlStrdup(content);
1.3 veillard 1067: else
1068: cur->content = NULL;
1069: return(cur);
1070: }
1071:
1.23 daniel 1072: /**
1073: * xmlNewReference:
1074: * @doc: the document
1075: * @name: the reference name, or the reference string with & and ;
1076: *
1077: * Creation of a new reference node.
1.36 daniel 1078: * Returns a pointer to the new node object.
1.23 daniel 1079: */
1.28 daniel 1080: xmlNodePtr
1081: xmlNewReference(xmlDocPtr doc, const CHAR *name) {
1.23 daniel 1082: xmlNodePtr cur;
1083: xmlEntityPtr ent;
1084:
1085: /*
1086: * Allocate a new node and fill the fields.
1087: */
1.57 ! daniel 1088: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.23 daniel 1089: if (cur == NULL) {
1090: fprintf(stderr, "xmlNewText : malloc failed\n");
1091: return(NULL);
1092: }
1093:
1094: cur->type = XML_ENTITY_REF_NODE;
1.28 daniel 1095: cur->doc = doc;
1.23 daniel 1096: cur->parent = NULL;
1097: cur->next = NULL;
1098: cur->prev = NULL;
1099: cur->childs = NULL;
1.32 daniel 1100: cur->last = NULL;
1.23 daniel 1101: cur->properties = NULL;
1102: if (name[0] == '&') {
1103: int len;
1104: name++;
1105: len = xmlStrlen(name);
1106: if (name[len - 1] == ';')
1107: cur->name = xmlStrndup(name, len - 1);
1108: else
1109: cur->name = xmlStrndup(name, len);
1110: } else
1111: cur->name = xmlStrdup(name);
1112: cur->ns = NULL;
1113: cur->nsDef = NULL;
1114:
1115: ent = xmlGetDocEntity(doc, cur->name);
1116: if (ent != NULL)
1117: cur->content = ent->content;
1118: else
1119: cur->content = NULL;
1120: return(cur);
1121: }
1122:
1123: /**
1124: * xmlNewDocText:
1125: * @doc: the document
1126: * @content: the text content
1127: *
1128: * Creation of a new text node within a document.
1.36 daniel 1129: * Returns a pointer to the new node object.
1.23 daniel 1130: */
1.28 daniel 1131: xmlNodePtr
1132: xmlNewDocText(xmlDocPtr doc, const CHAR *content) {
1.23 daniel 1133: xmlNodePtr cur;
1134:
1135: cur = xmlNewText(content);
1136: if (cur != NULL) cur->doc = doc;
1137: return(cur);
1138: }
1139:
1140: /**
1141: * xmlNewTextLen:
1142: * @content: the text content
1143: * @len: the text len.
1144: *
1145: * Creation of a new text node with an extra parameter for the content's lenght
1.36 daniel 1146: * Returns a pointer to the new node object.
1.21 daniel 1147: */
1.28 daniel 1148: xmlNodePtr
1149: xmlNewTextLen(const CHAR *content, int len) {
1.21 daniel 1150: xmlNodePtr cur;
1151:
1152: /*
1153: * Allocate a new node and fill the fields.
1154: */
1.57 ! daniel 1155: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.21 daniel 1156: if (cur == NULL) {
1157: fprintf(stderr, "xmlNewText : malloc failed\n");
1158: return(NULL);
1159: }
1160:
1.23 daniel 1161: cur->type = XML_TEXT_NODE;
1162: cur->doc = NULL;
1.21 daniel 1163: cur->parent = NULL;
1.23 daniel 1164: cur->prev = NULL;
1.21 daniel 1165: cur->next = NULL;
1166: cur->childs = NULL;
1.32 daniel 1167: cur->last = NULL;
1.21 daniel 1168: cur->properties = NULL;
1.23 daniel 1169: cur->type = XML_TEXT_NODE;
1.21 daniel 1170: cur->name = xmlStrdup(xmlStringText);
1171: cur->ns = NULL;
1172: cur->nsDef = NULL;
1173: if (content != NULL)
1174: cur->content = xmlStrndup(content, len);
1175: else
1176: cur->content = NULL;
1177: return(cur);
1178: }
1179:
1.23 daniel 1180: /**
1181: * xmlNewDocTextLen:
1182: * @doc: the document
1183: * @content: the text content
1184: * @len: the text len.
1185: *
1186: * Creation of a new text node with an extra content lenght parameter. The
1187: * text node pertain to a given document.
1.36 daniel 1188: * Returns a pointer to the new node object.
1.23 daniel 1189: */
1.28 daniel 1190: xmlNodePtr
1191: xmlNewDocTextLen(xmlDocPtr doc, const CHAR *content, int len) {
1.23 daniel 1192: xmlNodePtr cur;
1193:
1194: cur = xmlNewTextLen(content, len);
1195: if (cur != NULL) cur->doc = doc;
1196: return(cur);
1197: }
1198:
1199: /**
1200: * xmlNewComment:
1201: * @content: the comment content
1202: *
1203: * Creation of a new node containing a comment.
1.36 daniel 1204: * Returns a pointer to the new node object.
1.14 daniel 1205: */
1.28 daniel 1206: xmlNodePtr
1.37 daniel 1207: xmlNewComment(const CHAR *content) {
1.14 daniel 1208: xmlNodePtr cur;
1209:
1210: /*
1211: * Allocate a new node and fill the fields.
1212: */
1.57 ! daniel 1213: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.14 daniel 1214: if (cur == NULL) {
1.19 daniel 1215: fprintf(stderr, "xmlNewComment : malloc failed\n");
1.14 daniel 1216: return(NULL);
1217: }
1218:
1.23 daniel 1219: cur->type = XML_COMMENT_NODE;
1220: cur->doc = NULL;
1.14 daniel 1221: cur->parent = NULL;
1.23 daniel 1222: cur->prev = NULL;
1.14 daniel 1223: cur->next = NULL;
1224: cur->childs = NULL;
1.32 daniel 1225: cur->last = NULL;
1.14 daniel 1226: cur->properties = NULL;
1.23 daniel 1227: cur->type = XML_COMMENT_NODE;
1.18 daniel 1228: cur->name = xmlStrdup(xmlStringText);
1.16 daniel 1229: cur->ns = NULL;
1.19 daniel 1230: cur->nsDef = NULL;
1.14 daniel 1231: if (content != NULL)
1232: cur->content = xmlStrdup(content);
1233: else
1234: cur->content = NULL;
1235: return(cur);
1236: }
1237:
1.23 daniel 1238: /**
1.50 daniel 1239: * xmlNewCDataBlock:
1240: * @doc: the document
1241: * @content: the CData block content content
1242: * @len: the length of the block
1243: *
1244: * Creation of a new node containing a CData block.
1245: * Returns a pointer to the new node object.
1246: */
1247: xmlNodePtr
1248: xmlNewCDataBlock(xmlDocPtr doc, const CHAR *content, int len) {
1249: xmlNodePtr cur;
1250:
1251: /*
1252: * Allocate a new node and fill the fields.
1253: */
1.57 ! daniel 1254: cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.50 daniel 1255: if (cur == NULL) {
1256: fprintf(stderr, "xmlNewCDataBlock : malloc failed\n");
1257: return(NULL);
1258: }
1259:
1260: cur->type = XML_CDATA_SECTION_NODE;
1261: cur->doc = NULL;
1262: cur->parent = NULL;
1263: cur->prev = NULL;
1264: cur->next = NULL;
1265: cur->childs = NULL;
1266: cur->last = NULL;
1267: cur->properties = NULL;
1268: cur->name = xmlStrdup(xmlStringText);
1269: cur->ns = NULL;
1270: cur->nsDef = NULL;
1271: if ((content != NULL) && (len > 0)) {
1272: cur->content = xmlStrndup(content, len);
1273: } else
1274: cur->content = NULL;
1275: return(cur);
1276: }
1277:
1278: /**
1.36 daniel 1279: * xmlNewDocComment:
1.23 daniel 1280: * @doc: the document
1281: * @content: the comment content
1282: *
1283: * Creation of a new node containing a commentwithin a document.
1.36 daniel 1284: * Returns a pointer to the new node object.
1.23 daniel 1285: */
1.28 daniel 1286: xmlNodePtr
1.37 daniel 1287: xmlNewDocComment(xmlDocPtr doc, const CHAR *content) {
1.23 daniel 1288: xmlNodePtr cur;
1289:
1290: cur = xmlNewComment(content);
1291: if (cur != NULL) cur->doc = doc;
1292: return(cur);
1293: }
1294:
1295: /**
1296: * xmlNewChild:
1297: * @parent: the parent node
1298: * @ns: a namespace if any
1299: * @name: the name of the child
1300: * @content: the content of the child if any.
1301: *
1302: *
1303: * Creation of a new child element, added at the end of @parent childs list.
1.24 daniel 1304: * @ns and @content parameters are optionnal (NULL). If content is non NULL,
1305: * a child list containing the TEXTs and ENTITY_REFs node will be created.
1.36 daniel 1306: * Returns a pointer to the new node object.
1.1 veillard 1307: */
1.28 daniel 1308: xmlNodePtr
1309: xmlNewChild(xmlNodePtr parent, xmlNsPtr ns,
1.48 daniel 1310: const CHAR *name, const CHAR *content) {
1.1 veillard 1311: xmlNodePtr cur, prev;
1312:
1313: if (parent == NULL) {
1314: fprintf(stderr, "xmlNewChild : parent == NULL\n");
1315: return(NULL);
1316: }
1317:
1318: if (name == NULL) {
1319: fprintf(stderr, "xmlNewChild : name == NULL\n");
1320: return(NULL);
1321: }
1322:
1323: /*
1324: * Allocate a new node
1325: */
1.16 daniel 1326: if (ns == NULL)
1.24 daniel 1327: cur = xmlNewDocNode(parent->doc, parent->ns, name, content);
1.1 veillard 1328: else
1.24 daniel 1329: cur = xmlNewDocNode(parent->doc, ns, name, content);
1.1 veillard 1330: if (cur == NULL) return(NULL);
1331:
1332: /*
1333: * add the new element at the end of the childs list.
1334: */
1.25 daniel 1335: cur->type = XML_ELEMENT_NODE;
1.1 veillard 1336: cur->parent = parent;
1.23 daniel 1337: cur->doc = parent->doc;
1.1 veillard 1338: if (parent->childs == NULL) {
1339: parent->childs = cur;
1.32 daniel 1340: parent->last = cur;
1.1 veillard 1341: } else {
1.32 daniel 1342: prev = parent->last;
1.1 veillard 1343: prev->next = cur;
1.23 daniel 1344: cur->prev = prev;
1.32 daniel 1345: parent->last = cur;
1.1 veillard 1346: }
1347:
1348: return(cur);
1349: }
1350:
1.23 daniel 1351: /**
1.52 daniel 1352: * xmlAddSibling:
1353: * @cur: the child node
1354: * @elem: the new node
1355: *
1356: * Add a new element to the list of siblings of @cur
1357: * Returns the element or NULL in case of error.
1358: */
1359: xmlNodePtr
1360: xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) {
1361: xmlNodePtr parent;
1362:
1363: if (cur == NULL) {
1364: fprintf(stderr, "xmlAddSibling : cur == NULL\n");
1365: return(NULL);
1366: }
1367:
1368: if (elem == NULL) {
1369: fprintf(stderr, "xmlAddSibling : elem == NULL\n");
1370: return(NULL);
1371: }
1372:
1373: if ((cur->doc != NULL) && (elem->doc != NULL) &&
1374: (cur->doc != elem->doc)) {
1375: fprintf(stderr,
1376: "xmlAddSibling: Elements moved to a different document\n");
1377: }
1378:
1379: while (cur->next != NULL) cur = cur->next;
1380:
1381: if (elem->doc == NULL)
1382: elem->doc = cur->doc; /* the parent may not be linked to a doc ! */
1383:
1384: parent = cur->parent;
1385: elem->prev = cur;
1386: elem->next = NULL;
1387: elem->parent = parent;
1388: cur->next = elem;
1389: if (parent != NULL)
1390: parent->last = elem;
1391:
1392: return(elem);
1393: }
1394:
1395: /**
1.23 daniel 1396: * xmlAddChild:
1397: * @parent: the parent node
1398: * @cur: the child node
1399: *
1400: * Add a new child element, to @parent, at the end of the child list.
1.36 daniel 1401: * Returns the child or NULL in case of error.
1.2 veillard 1402: */
1.28 daniel 1403: xmlNodePtr
1404: xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) {
1.2 veillard 1405: xmlNodePtr prev;
1406:
1407: if (parent == NULL) {
1408: fprintf(stderr, "xmladdChild : parent == NULL\n");
1409: return(NULL);
1410: }
1411:
1412: if (cur == NULL) {
1413: fprintf(stderr, "xmladdChild : child == NULL\n");
1414: return(NULL);
1415: }
1416:
1.23 daniel 1417: if ((cur->doc != NULL) && (parent->doc != NULL) &&
1418: (cur->doc != parent->doc)) {
1419: fprintf(stderr, "Elements moved to a different document\n");
1420: }
1421:
1.2 veillard 1422: /*
1423: * add the new element at the end of the childs list.
1424: */
1425: cur->parent = parent;
1.23 daniel 1426: cur->doc = parent->doc; /* the parent may not be linked to a doc ! */
1.32 daniel 1427:
1.24 daniel 1428: /*
1429: * Handle the case where parent->content != NULL, in that case it will
1430: * create a intermediate TEXT node.
1431: */
1432: if (parent->content != NULL) {
1433: xmlNodePtr text;
1434:
1435: text = xmlNewDocText(parent->doc, parent->content);
1436: if (text != NULL) {
1437: text->next = parent->childs;
1438: if (text->next != NULL)
1439: text->next->prev = text;
1440: parent->childs = text;
1.34 daniel 1441: UPDATE_LAST_CHILD(parent)
1.57 ! daniel 1442: xmlFree(parent->content);
1.24 daniel 1443: parent->content = NULL;
1444: }
1445: }
1.2 veillard 1446: if (parent->childs == NULL) {
1447: parent->childs = cur;
1.32 daniel 1448: parent->last = cur;
1.2 veillard 1449: } else {
1.32 daniel 1450: prev = parent->last;
1.2 veillard 1451: prev->next = cur;
1.23 daniel 1452: cur->prev = prev;
1.32 daniel 1453: parent->last = cur;
1.2 veillard 1454: }
1455:
1456: return(cur);
1457: }
1458:
1.23 daniel 1459: /**
1460: * xmlGetLastChild:
1461: * @parent: the parent node
1462: *
1463: * Search the last child of a node.
1.36 daniel 1464: * Returns the last child or NULL if none.
1.21 daniel 1465: */
1.28 daniel 1466: xmlNodePtr
1467: xmlGetLastChild(xmlNodePtr parent) {
1.21 daniel 1468: if (parent == NULL) {
1469: fprintf(stderr, "xmlGetLastChild : parent == NULL\n");
1470: return(NULL);
1471: }
1.32 daniel 1472: return(parent->last);
1.21 daniel 1473: }
1474:
1.23 daniel 1475: /**
1476: * xmlFreeNodeList:
1477: * @cur: the first node in the list
1478: *
1479: * Free a node and all its siblings, this is a recursive behaviour, all
1480: * the childs are freed too.
1.1 veillard 1481: */
1.28 daniel 1482: void
1483: xmlFreeNodeList(xmlNodePtr cur) {
1.1 veillard 1484: xmlNodePtr next;
1485: if (cur == NULL) {
1486: fprintf(stderr, "xmlFreeNodeList : node == NULL\n");
1487: return;
1488: }
1489: while (cur != NULL) {
1490: next = cur->next;
1491: xmlFreeNode(cur);
1492: cur = next;
1493: }
1494: }
1495:
1.23 daniel 1496: /**
1497: * xmlFreeNode:
1498: * @cur: the node
1499: *
1500: * Free a node, this is a recursive behaviour, all the childs are freed too.
1.1 veillard 1501: */
1.28 daniel 1502: void
1503: xmlFreeNode(xmlNodePtr cur) {
1.1 veillard 1504: if (cur == NULL) {
1505: fprintf(stderr, "xmlFreeNode : node == NULL\n");
1506: return;
1507: }
1.23 daniel 1508: cur->doc = NULL;
1509: cur->parent = NULL;
1510: cur->next = NULL;
1511: cur->prev = NULL;
1512: if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
1.1 veillard 1513: if (cur->properties != NULL) xmlFreePropList(cur->properties);
1.23 daniel 1514: if (cur->type != XML_ENTITY_REF_NODE)
1.57 ! daniel 1515: if (cur->content != NULL) xmlFree(cur->content);
! 1516: if (cur->name != NULL) xmlFree((char *) cur->name);
1.19 daniel 1517: if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef);
1.1 veillard 1518: memset(cur, -1, sizeof(xmlNode));
1.57 ! daniel 1519: xmlFree(cur);
1.1 veillard 1520: }
1521:
1.28 daniel 1522: /**
1523: * xmlUnlinkNode:
1524: * @cur: the node
1525: *
1526: * Unlink a node from it's current context, the node is not freed
1527: */
1528: void
1529: xmlUnlinkNode(xmlNodePtr cur) {
1530: if (cur == NULL) {
1531: fprintf(stderr, "xmlUnlinkNode : node == NULL\n");
1532: return;
1533: }
1534: if ((cur->parent != NULL) && (cur->parent->childs == cur))
1535: cur->parent->childs = cur->next;
1.32 daniel 1536: if ((cur->parent != NULL) && (cur->parent->last == cur))
1537: cur->parent->last = cur->prev;
1.28 daniel 1538: if (cur->next != NULL)
1539: cur->next->prev = cur->prev;
1540: if (cur->prev != NULL)
1541: cur->prev->next = cur->next;
1542: cur->next = cur->prev = NULL;
1543: cur->parent = NULL;
1544: }
1545:
1.1 veillard 1546: /************************************************************************
1547: * *
1.31 daniel 1548: * Copy operations *
1549: * *
1550: ************************************************************************/
1551:
1552: /**
1553: * xmlCopyNamespace:
1554: * @cur: the namespace
1555: *
1556: * Do a copy of the namespace.
1557: *
1558: * Returns: a new xmlNsPtr, or NULL in case of error.
1559: */
1560: xmlNsPtr
1561: xmlCopyNamespace(xmlNsPtr cur) {
1562: xmlNsPtr ret;
1563:
1564: if (cur == NULL) return(NULL);
1565: switch (cur->type) {
1566: case XML_GLOBAL_NAMESPACE:
1567: ret = xmlNewGlobalNs(NULL, cur->href, cur->prefix);
1568: break;
1569: case XML_LOCAL_NAMESPACE:
1570: ret = xmlNewNs(NULL, cur->href, cur->prefix);
1571: break;
1572: default:
1573: fprintf(stderr, "xmlCopyNamespace: unknown type %d\n", cur->type);
1574: return(NULL);
1575: }
1576: return(ret);
1577: }
1578:
1579: /**
1580: * xmlCopyNamespaceList:
1581: * @cur: the first namespace
1582: *
1583: * Do a copy of an namespace list.
1584: *
1585: * Returns: a new xmlNsPtr, or NULL in case of error.
1586: */
1587: xmlNsPtr
1588: xmlCopyNamespaceList(xmlNsPtr cur) {
1589: xmlNsPtr ret = NULL;
1590: xmlNsPtr p = NULL,q;
1591:
1592: while (cur != NULL) {
1593: q = xmlCopyNamespace(cur);
1594: if (p == NULL) {
1595: ret = p = q;
1596: } else {
1597: p->next = q;
1598: p = q;
1599: }
1600: cur = cur->next;
1601: }
1602: return(ret);
1603: }
1604:
1605: /**
1606: * xmlCopyProp:
1.56 daniel 1607: * @target: the element where the attribute will be grafted
1.31 daniel 1608: * @cur: the attribute
1609: *
1610: * Do a copy of the attribute.
1611: *
1612: * Returns: a new xmlAttrPtr, or NULL in case of error.
1613: */
1614: xmlAttrPtr
1.56 daniel 1615: xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) {
1.31 daniel 1616: xmlAttrPtr ret;
1617:
1618: if (cur == NULL) return(NULL);
1619: if (cur->val != NULL)
1620: ret = xmlNewDocProp(cur->val->doc, cur->name, NULL);
1621: else
1622: ret = xmlNewDocProp(NULL, cur->name, NULL);
1623: if (ret == NULL) return(NULL);
1.56 daniel 1624:
1625: if ((cur->ns != NULL) && (target != NULL)) {
1626: xmlNsPtr ns;
1627:
1628: ns = xmlSearchNs(target->doc, target, cur->ns->prefix);
1629: ret->ns = ns;
1630: } else
1631: ret->ns = NULL;
1632:
1.31 daniel 1633: if (cur->val != NULL)
1634: ret->val = xmlCopyNodeList(cur->val);
1635: return(ret);
1636: }
1637:
1638: /**
1639: * xmlCopyPropList:
1.56 daniel 1640: * @target: the element where the attributes will be grafted
1.31 daniel 1641: * @cur: the first attribute
1642: *
1643: * Do a copy of an attribute list.
1644: *
1645: * Returns: a new xmlAttrPtr, or NULL in case of error.
1646: */
1647: xmlAttrPtr
1.56 daniel 1648: xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) {
1.31 daniel 1649: xmlAttrPtr ret = NULL;
1650: xmlAttrPtr p = NULL,q;
1651:
1652: while (cur != NULL) {
1.56 daniel 1653: q = xmlCopyProp(target, cur);
1.31 daniel 1654: if (p == NULL) {
1655: ret = p = q;
1656: } else {
1657: p->next = q;
1658: p = q;
1659: }
1660: cur = cur->next;
1661: }
1662: return(ret);
1663: }
1664:
1665: /*
1666: * NOTE about the CopyNode operations !
1667: *
1668: * They are splitted into external and internal parts for one
1669: * tricky reason: namespaces. Doing a direct copy of a node
1670: * say RPM:Copyright without changing the namespace pointer to
1671: * something else can produce stale links. One way to do it is
1672: * to keep a reference counter but this doesn't work as soon
1673: * as one move the element or the subtree out of the scope of
1674: * the existing namespace. The actual solution seems to add
1675: * a copy of the namespace at the top of the copied tree if
1676: * not available in the subtree.
1677: * Hence two functions, the public front-end call the inner ones
1678: */
1679:
1680: static xmlNodePtr
1681: xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);
1682:
1683: static xmlNodePtr
1684: xmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent,
1685: int recursive) {
1686: xmlNodePtr ret;
1687:
1688: if (node == NULL) return(NULL);
1689: /*
1690: * Allocate a new node and fill the fields.
1691: */
1.57 ! daniel 1692: ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1.31 daniel 1693: if (ret == NULL) {
1694: fprintf(stderr, "xmlStaticCopyNode : malloc failed\n");
1695: return(NULL);
1696: }
1697:
1698: ret->type = node->type;
1699: ret->doc = doc;
1700: ret->parent = parent;
1701: ret->next = NULL;
1702: ret->prev = NULL;
1703: ret->childs = NULL;
1.32 daniel 1704: ret->last = NULL;
1.31 daniel 1705: ret->properties = NULL;
1706: if (node->name != NULL)
1707: ret->name = xmlStrdup(node->name);
1708: else
1709: ret->name = NULL;
1710: ret->ns = NULL;
1711: ret->nsDef = NULL;
1712: if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE))
1713: ret->content = xmlStrdup(node->content);
1714: else
1715: ret->content = NULL;
1.39 daniel 1716: #ifndef XML_WITHOUT_CORBA
1.31 daniel 1717: ret->_private = NULL;
1718: ret->vepv = NULL;
1719: #endif
1720: if (parent != NULL)
1721: xmlAddChild(parent, ret);
1722:
1723: if (!recursive) return(ret);
1724: if (node->nsDef != NULL)
1725: ret->nsDef = xmlCopyNamespaceList(node->nsDef);
1726:
1727: if (node->ns != NULL) {
1728: xmlNsPtr ns;
1729:
1730: ns = xmlSearchNs(doc, ret, node->ns->prefix);
1731: if (ns == NULL) {
1732: /*
1733: * Humm, we are copying an element whose namespace is defined
1734: * out of the new tree scope. Search it in the original tree
1735: * and add it at the top of the new tree
1736: */
1737: ns = xmlSearchNs(node->doc, node, node->ns->prefix);
1738: if (ns != NULL) {
1739: xmlNodePtr root = ret;
1740:
1741: while (root->parent != NULL) root = root->parent;
1742: xmlNewNs(root, ns->href, ns->prefix);
1743: }
1744: } else {
1745: /*
1746: * reference the existing namespace definition in our own tree.
1747: */
1748: ret->ns = ns;
1749: }
1750: }
1.56 daniel 1751: if (node->properties != NULL)
1752: ret->properties = xmlCopyPropList(ret, node->properties);
1.31 daniel 1753: if (node->childs != NULL)
1754: ret->childs = xmlStaticCopyNodeList(node->childs, doc, ret);
1.34 daniel 1755: UPDATE_LAST_CHILD(ret)
1.31 daniel 1756: return(ret);
1757: }
1758:
1759: static xmlNodePtr
1760: xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
1761: xmlNodePtr ret = NULL;
1762: xmlNodePtr p = NULL,q;
1763:
1764: while (node != NULL) {
1765: q = xmlStaticCopyNode(node, doc, parent, 1);
1766: if (parent == NULL) {
1767: if (ret == NULL) ret = q;
1768: } else {
1769: if (ret == NULL) {
1770: q->prev = NULL;
1771: ret = p = q;
1772: } else {
1773: p->next = q;
1774: q->prev = p;
1775: p = q;
1776: }
1777: }
1778: node = node->next;
1779: }
1780: return(ret);
1781: }
1782:
1783: /**
1784: * xmlCopyNode:
1785: * @node: the node
1786: * @recursive: if 1 do a recursive copy.
1787: *
1788: * Do a copy of the node.
1789: *
1790: * Returns: a new xmlNodePtr, or NULL in case of error.
1791: */
1792: xmlNodePtr
1793: xmlCopyNode(xmlNodePtr node, int recursive) {
1794: xmlNodePtr ret;
1795:
1796: ret = xmlStaticCopyNode(node, NULL, NULL, recursive);
1797: return(ret);
1798: }
1799:
1800: /**
1801: * xmlCopyNodeList:
1802: * @node: the first node in the list.
1803: *
1804: * Do a recursive copy of the node list.
1805: *
1806: * Returns: a new xmlNodePtr, or NULL in case of error.
1807: */
1808: xmlNodePtr xmlCopyNodeList(xmlNodePtr node) {
1809: xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL);
1810: return(ret);
1811: }
1812:
1813: /**
1814: * xmlCopyElement:
1815: * @elem: the element
1816: *
1817: * Do a copy of the element definition.
1818: *
1819: * Returns: a new xmlElementPtr, or NULL in case of error.
1820: xmlElementPtr
1821: xmlCopyElement(xmlElementPtr elem) {
1822: xmlElementPtr ret;
1823:
1824: if (elem == NULL) return(NULL);
1825: ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content);
1826: if (ret == NULL) return(NULL);
1827: if (!recursive) return(ret);
1828: if (elem->properties != NULL)
1829: ret->properties = xmlCopyPropList(elem->properties);
1830:
1831: if (elem->nsDef != NULL)
1832: ret->nsDef = xmlCopyNamespaceList(elem->nsDef);
1833: if (elem->childs != NULL)
1834: ret->childs = xmlCopyElementList(elem->childs);
1835: return(ret);
1836: }
1837: */
1838:
1839: /**
1840: * xmlCopyDtd:
1841: * @dtd: the dtd
1842: *
1843: * Do a copy of the dtd.
1844: *
1845: * Returns: a new xmlDtdPtr, or NULL in case of error.
1846: */
1847: xmlDtdPtr
1848: xmlCopyDtd(xmlDtdPtr dtd) {
1849: xmlDtdPtr ret;
1850:
1851: if (dtd == NULL) return(NULL);
1852: ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID);
1853: if (ret == NULL) return(NULL);
1854: if (dtd->entities != NULL)
1855: ret->entities = (void *) xmlCopyEntitiesTable(
1856: (xmlEntitiesTablePtr) dtd->entities);
1.35 daniel 1857: if (dtd->notations != NULL)
1858: ret->notations = (void *) xmlCopyNotationTable(
1859: (xmlNotationTablePtr) dtd->notations);
1860: if (dtd->elements != NULL)
1861: ret->elements = (void *) xmlCopyElementTable(
1862: (xmlElementTablePtr) dtd->elements);
1863: if (dtd->attributes != NULL)
1864: ret->attributes = (void *) xmlCopyAttributeTable(
1865: (xmlAttributeTablePtr) dtd->attributes);
1.31 daniel 1866: return(ret);
1867: }
1868:
1869: /**
1870: * xmlCopyDoc:
1871: * @doc: the document
1872: * @recursive: if 1 do a recursive copy.
1873: *
1874: * Do a copy of the document info. If recursive, the content tree will
1875: * be copied too as well as Dtd, namespaces and entities.
1876: *
1877: * Returns: a new xmlDocPtr, or NULL in case of error.
1878: */
1879: xmlDocPtr
1880: xmlCopyDoc(xmlDocPtr doc, int recursive) {
1881: xmlDocPtr ret;
1882:
1883: if (doc == NULL) return(NULL);
1884: ret = xmlNewDoc(doc->version);
1885: if (ret == NULL) return(NULL);
1886: if (doc->name != NULL)
1.57 ! daniel 1887: ret->name = xmlMemStrdup(doc->name);
1.31 daniel 1888: if (doc->encoding != NULL)
1889: ret->encoding = xmlStrdup(doc->encoding);
1890: ret->compression = doc->compression;
1891: ret->standalone = doc->standalone;
1892: if (!recursive) return(ret);
1893:
1894: if (doc->intSubset != NULL)
1895: ret->intSubset = xmlCopyDtd(doc->intSubset);
1896: if (doc->oldNs != NULL)
1897: ret->oldNs = xmlCopyNamespaceList(doc->oldNs);
1898: if (doc->root != NULL)
1899: ret->root = xmlStaticCopyNodeList(doc->root, ret, NULL);
1900: return(ret);
1901: }
1902:
1903: /************************************************************************
1904: * *
1.1 veillard 1905: * Content access functions *
1906: * *
1907: ************************************************************************/
1908:
1.23 daniel 1909: /**
1.52 daniel 1910: * xmlNodeSetLang:
1911: * @cur: the node being changed
1912: * @lang: the langage description
1913: *
1914: * Searches the language of a node, i.e. the values of the xml:lang
1915: * attribute or the one carried by the nearest ancestor.
1916: *
1917: * Returns a pointer to the lang value, or NULL if not found
1918: */
1919: void
1920: xmlNodeSetLang(xmlNodePtr cur, const CHAR *lang) {
1.55 daniel 1921: /* TODO xmlNodeSetLang check against the production [33] LanguageID */
1.54 daniel 1922: xmlSetProp(cur, BAD_CAST "xml:lang", lang);
1.52 daniel 1923: }
1924:
1925: /**
1926: * xmlNodeGetLang:
1927: * @cur: the node being checked
1928: *
1929: * Searches the language of a node, i.e. the values of the xml:lang
1930: * attribute or the one carried by the nearest ancestor.
1931: *
1932: * Returns a pointer to the lang value, or NULL if not found
1933: */
1934: const CHAR *
1935: xmlNodeGetLang(xmlNodePtr cur) {
1936: const CHAR *lang;
1937:
1938: while (cur != NULL) {
1.54 daniel 1939: lang = xmlGetProp(cur, BAD_CAST "xml:lang");
1.52 daniel 1940: if (lang != NULL)
1941: return(lang);
1942: cur = cur->parent;
1943: }
1944: return(NULL);
1945: }
1946:
1947: /**
1.28 daniel 1948: * xmlNodeGetContent:
1949: * @cur: the node being read
1950: *
1951: * Read the value of a node, this can be either the text carried
1952: * directly by this node if it's a TEXT node or the aggregate string
1953: * of the values carried by this node child's (TEXT and ENTITY_REF).
1954: * Entity references are substitued.
1.36 daniel 1955: * Returns a new CHAR * or NULL if no content is available.
1.38 daniel 1956: * It's up to the caller to free the memory.
1.28 daniel 1957: */
1958: CHAR *
1959: xmlNodeGetContent(xmlNodePtr cur) {
1960: if (cur == NULL) return(NULL);
1961: switch (cur->type) {
1962: case XML_DOCUMENT_FRAG_NODE:
1963: case XML_ELEMENT_NODE:
1964: return(xmlNodeListGetString(cur->doc, cur->childs, 1));
1965: break;
1.52 daniel 1966: case XML_ATTRIBUTE_NODE: {
1967: xmlAttrPtr attr = (xmlAttrPtr) cur;
1968: if (attr->node != NULL)
1969: return(xmlNodeListGetString(attr->node->doc, attr->val, 1));
1970: else
1971: return(xmlNodeListGetString(NULL, attr->val, 1));
1972: break;
1973: }
1974: case XML_PI_NODE:
1975: if (cur->content != NULL)
1976: return(xmlStrdup(cur->content));
1977: return(NULL);
1.28 daniel 1978: case XML_ENTITY_REF_NODE:
1979: case XML_ENTITY_NODE:
1980: case XML_COMMENT_NODE:
1981: case XML_DOCUMENT_NODE:
1982: case XML_DOCUMENT_TYPE_NODE:
1983: case XML_NOTATION_NODE:
1984: return(NULL);
1.50 daniel 1985: case XML_CDATA_SECTION_NODE:
1.28 daniel 1986: case XML_TEXT_NODE:
1987: if (cur->content != NULL)
1988: return(xmlStrdup(cur->content));
1989: return(NULL);
1990: }
1991: return(NULL);
1992: }
1993:
1994: /**
1.23 daniel 1995: * xmlNodeSetContent:
1996: * @cur: the node being modified
1997: * @content: the new value of the content
1998: *
1999: * Replace the content of a node.
1.1 veillard 2000: */
1.28 daniel 2001: void
2002: xmlNodeSetContent(xmlNodePtr cur, const CHAR *content) {
1.1 veillard 2003: if (cur == NULL) {
2004: fprintf(stderr, "xmlNodeSetContent : node == NULL\n");
2005: return;
2006: }
1.28 daniel 2007: switch (cur->type) {
2008: case XML_DOCUMENT_FRAG_NODE:
2009: case XML_ELEMENT_NODE:
2010: if (cur->content != NULL) {
1.57 ! daniel 2011: xmlFree(cur->content);
1.28 daniel 2012: cur->content = NULL;
2013: }
1.57 ! daniel 2014: if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
1.28 daniel 2015: cur->childs = xmlStringGetNodeList(cur->doc, content);
1.34 daniel 2016: UPDATE_LAST_CHILD(cur)
1.28 daniel 2017: break;
2018: case XML_ATTRIBUTE_NODE:
2019: break;
2020: case XML_TEXT_NODE:
2021: case XML_CDATA_SECTION_NODE:
2022: case XML_ENTITY_REF_NODE:
2023: case XML_ENTITY_NODE:
2024: case XML_PI_NODE:
2025: case XML_COMMENT_NODE:
1.57 ! daniel 2026: if (cur->content != NULL) xmlFree(cur->content);
! 2027: if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
1.32 daniel 2028: cur->last = cur->childs = NULL;
1.28 daniel 2029: if (content != NULL)
2030: cur->content = xmlStrdup(content);
2031: else
2032: cur->content = NULL;
1.53 daniel 2033: break;
1.28 daniel 2034: case XML_DOCUMENT_NODE:
2035: case XML_DOCUMENT_TYPE_NODE:
2036: break;
2037: case XML_NOTATION_NODE:
2038: break;
2039: }
1.1 veillard 2040: }
2041:
1.23 daniel 2042: /**
2043: * xmlNodeSetContentLen:
2044: * @cur: the node being modified
2045: * @content: the new value of the content
2046: * @len: the size of @content
2047: *
2048: * Replace the content of a node.
1.21 daniel 2049: */
1.28 daniel 2050: void
2051: xmlNodeSetContentLen(xmlNodePtr cur, const CHAR *content, int len) {
1.21 daniel 2052: if (cur == NULL) {
1.28 daniel 2053: fprintf(stderr, "xmlNodeSetContentLen : node == NULL\n");
1.21 daniel 2054: return;
2055: }
1.28 daniel 2056: switch (cur->type) {
2057: case XML_DOCUMENT_FRAG_NODE:
2058: case XML_ELEMENT_NODE:
2059: if (cur->content != NULL) {
1.57 ! daniel 2060: xmlFree(cur->content);
1.28 daniel 2061: cur->content = NULL;
2062: }
1.57 ! daniel 2063: if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
1.28 daniel 2064: cur->childs = xmlStringLenGetNodeList(cur->doc, content, len);
1.34 daniel 2065: UPDATE_LAST_CHILD(cur)
1.28 daniel 2066: break;
2067: case XML_ATTRIBUTE_NODE:
2068: break;
2069: case XML_TEXT_NODE:
2070: case XML_CDATA_SECTION_NODE:
2071: case XML_ENTITY_REF_NODE:
2072: case XML_ENTITY_NODE:
2073: case XML_PI_NODE:
2074: case XML_COMMENT_NODE:
1.57 ! daniel 2075: if (cur->content != NULL) xmlFree(cur->content);
! 2076: if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
1.32 daniel 2077: cur->childs = cur->last = NULL;
1.28 daniel 2078: if (content != NULL)
2079: cur->content = xmlStrndup(content, len);
2080: else
2081: cur->content = NULL;
1.53 daniel 2082: break;
1.28 daniel 2083: case XML_DOCUMENT_NODE:
2084: case XML_DOCUMENT_TYPE_NODE:
2085: break;
2086: case XML_NOTATION_NODE:
1.57 ! daniel 2087: if (cur->content != NULL) xmlFree(cur->content);
! 2088: if (cur->childs != NULL) xmlFreeNodeList(cur->childs);
1.32 daniel 2089: cur->childs = cur->last = NULL;
1.28 daniel 2090: if (content != NULL)
2091: cur->content = xmlStrndup(content, len);
2092: else
2093: cur->content = NULL;
2094: break;
2095: }
1.21 daniel 2096: }
2097:
1.23 daniel 2098: /**
1.28 daniel 2099: * xmlNodeAddContentLen:
1.23 daniel 2100: * @cur: the node being modified
2101: * @content: extra content
1.28 daniel 2102: * @len: the size of @content
1.23 daniel 2103: *
2104: * Append the extra substring to the node content.
1.21 daniel 2105: */
1.28 daniel 2106: void
2107: xmlNodeAddContentLen(xmlNodePtr cur, const CHAR *content, int len) {
1.21 daniel 2108: if (cur == NULL) {
1.28 daniel 2109: fprintf(stderr, "xmlNodeAddContentLen : node == NULL\n");
1.21 daniel 2110: return;
2111: }
1.28 daniel 2112: if (len <= 0) return;
2113: switch (cur->type) {
2114: case XML_DOCUMENT_FRAG_NODE:
2115: case XML_ELEMENT_NODE: {
2116: xmlNodePtr last = NULL, new;
2117:
2118: if (cur->childs != NULL) {
1.32 daniel 2119: last = cur->last;
1.28 daniel 2120: } else {
2121: if (cur->content != NULL) {
2122: cur->childs = xmlStringGetNodeList(cur->doc, cur->content);
1.34 daniel 2123: UPDATE_LAST_CHILD(cur)
1.57 ! daniel 2124: xmlFree(cur->content);
1.28 daniel 2125: cur->content = NULL;
1.32 daniel 2126: last = cur->last;
1.28 daniel 2127: }
2128: }
1.31 daniel 2129: new = xmlNewTextLen(content, len);
1.28 daniel 2130: if (new != NULL) {
2131: xmlAddChild(cur, new);
1.32 daniel 2132: if ((last != NULL) && (last->next == new)) {
1.28 daniel 2133: xmlTextMerge(last, new);
1.32 daniel 2134: }
1.28 daniel 2135: }
2136: break;
2137: }
2138: case XML_ATTRIBUTE_NODE:
2139: break;
2140: case XML_TEXT_NODE:
2141: case XML_CDATA_SECTION_NODE:
2142: case XML_ENTITY_REF_NODE:
2143: case XML_ENTITY_NODE:
2144: case XML_PI_NODE:
2145: case XML_COMMENT_NODE:
2146: if (content != NULL)
2147: cur->content = xmlStrncat(cur->content, content, len);
2148: case XML_DOCUMENT_NODE:
2149: case XML_DOCUMENT_TYPE_NODE:
2150: break;
2151: case XML_NOTATION_NODE:
2152: if (content != NULL)
2153: cur->content = xmlStrncat(cur->content, content, len);
2154: break;
2155: }
1.21 daniel 2156: }
2157:
1.23 daniel 2158: /**
1.28 daniel 2159: * xmlNodeAddContent:
1.23 daniel 2160: * @cur: the node being modified
2161: * @content: extra content
2162: *
2163: * Append the extra substring to the node content.
1.21 daniel 2164: */
1.28 daniel 2165: void
2166: xmlNodeAddContent(xmlNodePtr cur, const CHAR *content) {
2167: int len;
2168:
1.21 daniel 2169: if (cur == NULL) {
2170: fprintf(stderr, "xmlNodeAddContent : node == NULL\n");
2171: return;
2172: }
1.28 daniel 2173: if (content == NULL) return;
2174: len = xmlStrlen(content);
2175: xmlNodeAddContentLen(cur, content, len);
2176: }
2177:
2178: /**
2179: * xmlTextMerge:
2180: * @first: the first text node
2181: * @second: the second text node being merged
2182: *
2183: * Merge two text nodes into one
1.36 daniel 2184: * Returns the first text node augmented
1.28 daniel 2185: */
2186: xmlNodePtr
2187: xmlTextMerge(xmlNodePtr first, xmlNodePtr second) {
2188: if (first == NULL) return(second);
2189: if (second == NULL) return(first);
2190: if (first->type != XML_TEXT_NODE) return(first);
2191: if (second->type != XML_TEXT_NODE) return(first);
2192: xmlNodeAddContent(first, second->content);
2193: xmlUnlinkNode(second);
2194: xmlFreeNode(second);
2195: return(first);
1.21 daniel 2196: }
2197:
1.23 daniel 2198: /**
1.52 daniel 2199: * xmlGetNsList:
2200: * @doc: the document
2201: * @node: the current node
2202: *
2203: * Search all the namespace applying to a given element.
2204: * Returns an NULL terminated array of all the xmlNsPtr found
2205: * that need to be freed by the caller or NULL if no
2206: * namespace if defined
2207: */
2208: xmlNsPtr *
2209: xmlGetNsList(xmlDocPtr doc, xmlNodePtr node) {
2210: xmlNsPtr cur;
2211: xmlNsPtr *ret = NULL;
2212: int nbns = 0;
2213: int maxns = 10;
2214: int i;
2215:
2216: while (node != NULL) {
2217: cur = node->nsDef;
2218: while (cur != NULL) {
2219: if (ret == NULL) {
1.57 ! daniel 2220: ret = (xmlNsPtr *) xmlMalloc((maxns + 1) * sizeof(xmlNsPtr));
1.52 daniel 2221: if (ret == NULL) {
2222: fprintf(stderr, "xmlGetNsList : out of memory!\n");
2223: return(NULL);
2224: }
2225: ret[nbns] = NULL;
2226: }
2227: for (i = 0;i < nbns;i++) {
2228: if ((cur->prefix == ret[i]->prefix) ||
2229: (!xmlStrcmp(cur->prefix, ret[i]->prefix))) break;
2230: }
2231: if (i >= nbns) {
2232: if (nbns >= maxns) {
2233: maxns *= 2;
1.57 ! daniel 2234: ret = (xmlNsPtr *) xmlRealloc(ret,
1.52 daniel 2235: (maxns + 1) * sizeof(xmlNsPtr));
2236: if (ret == NULL) {
2237: fprintf(stderr, "xmlGetNsList : realloc failed!\n");
2238: return(NULL);
2239: }
2240: }
2241: ret[nbns++] = cur;
2242: ret[nbns] = NULL;
2243: }
2244:
2245: cur = cur->next;
2246: }
2247: node = node->parent;
2248: }
2249: return(ret);
2250: }
2251:
2252: /**
1.23 daniel 2253: * xmlSearchNs:
2254: * @doc: the document
2255: * @node: the current node
2256: * @nameSpace: the namespace string
2257: *
1.16 daniel 2258: * Search a Ns registered under a given name space for a document.
1.23 daniel 2259: * recurse on the parents until it finds the defined namespace
2260: * or return NULL otherwise.
2261: * @nameSpace can be NULL, this is a search for the default namespace.
1.36 daniel 2262: * Returns the namespace pointer or NULL.
1.3 veillard 2263: */
1.28 daniel 2264: xmlNsPtr
2265: xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const CHAR *nameSpace) {
1.16 daniel 2266: xmlNsPtr cur;
1.3 veillard 2267:
1.19 daniel 2268: while (node != NULL) {
2269: cur = node->nsDef;
2270: while (cur != NULL) {
2271: if ((cur->prefix == NULL) && (nameSpace == NULL))
2272: return(cur);
2273: if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2274: (!xmlStrcmp(cur->prefix, nameSpace)))
2275: return(cur);
2276: cur = cur->next;
2277: }
2278: node = node->parent;
2279: }
2280: if (doc != NULL) {
2281: cur = doc->oldNs;
2282: while (cur != NULL) {
2283: if ((cur->prefix != NULL) && (nameSpace != NULL) &&
2284: (!xmlStrcmp(cur->prefix, nameSpace)))
2285: return(cur);
2286: cur = cur->next;
2287: }
2288: }
2289: return(NULL);
2290: }
1.3 veillard 2291:
1.23 daniel 2292: /**
2293: * xmlSearchNsByHref:
2294: * @doc: the document
2295: * @node: the current node
2296: * @href: the namespace value
2297: *
2298: * Search a Ns aliasing a given URI. Recurse on the parents until it finds
2299: * the defined namespace or return NULL otherwise.
1.36 daniel 2300: * Returns the namespace pointer or NULL.
1.19 daniel 2301: */
1.28 daniel 2302: xmlNsPtr
2303: xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const CHAR *href) {
1.19 daniel 2304: xmlNsPtr cur;
2305:
2306: while (node != NULL) {
2307: cur = node->nsDef;
2308: while (cur != NULL) {
2309: if ((cur->href != NULL) && (href != NULL) &&
2310: (!xmlStrcmp(cur->href, href)))
2311: return(cur);
2312: cur = cur->next;
2313: }
2314: node = node->parent;
2315: }
2316: if (doc != NULL) {
2317: cur = doc->oldNs;
2318: while (cur != NULL) {
2319: if ((cur->href != NULL) && (href != NULL) &&
2320: (!xmlStrcmp(cur->href, href)))
2321: return(cur);
2322: cur = cur->next;
2323: }
1.3 veillard 2324: }
2325: return(NULL);
2326: }
2327:
1.23 daniel 2328: /**
2329: * xmlGetProp:
2330: * @node: the node
2331: * @name: the attribute name
2332: *
2333: * Search and get the value of an attribute associated to a node
2334: * This does the entity substitution.
1.36 daniel 2335: * Returns the attribute value or NULL if not found.
1.9 veillard 2336: */
1.31 daniel 2337: CHAR *xmlGetProp(xmlNodePtr node, const CHAR *name) {
1.20 daniel 2338: xmlAttrPtr prop = node->properties;
1.9 veillard 2339:
2340: while (prop != NULL) {
1.34 daniel 2341: if (!xmlStrcmp(prop->name, name)) {
2342: CHAR *ret;
2343:
2344: ret = xmlNodeListGetString(node->doc, prop->val, 1);
1.54 daniel 2345: if (ret == NULL) return(xmlStrdup((CHAR *)""));
1.34 daniel 2346: return(ret);
2347: }
1.9 veillard 2348: prop = prop->next;
2349: }
1.10 veillard 2350: return(NULL);
1.13 daniel 2351: }
2352:
1.23 daniel 2353: /**
2354: * xmlSetProp:
2355: * @node: the node
2356: * @name: the attribute name
2357: * @value: the attribute value
2358: *
2359: * Set (or reset) an attribute carried by a node.
1.36 daniel 2360: * Returns the attribute pointer.
1.13 daniel 2361: */
1.28 daniel 2362: xmlAttrPtr
2363: xmlSetProp(xmlNodePtr node, const CHAR *name, const CHAR *value) {
1.20 daniel 2364: xmlAttrPtr prop = node->properties;
1.13 daniel 2365:
2366: while (prop != NULL) {
2367: if (!xmlStrcmp(prop->name, name)) {
1.23 daniel 2368: if (prop->val != NULL)
1.57 ! daniel 2369: xmlFreeNodeList(prop->val);
1.23 daniel 2370: prop->val = NULL;
1.13 daniel 2371: if (value != NULL)
1.24 daniel 2372: prop->val = xmlStringGetNodeList(node->doc, value);
1.13 daniel 2373: return(prop);
2374: }
2375: prop = prop->next;
2376: }
2377: prop = xmlNewProp(node, name, value);
2378: return(prop);
1.9 veillard 2379: }
2380:
1.23 daniel 2381: /**
2382: * xmlNodeIsText:
2383: * @node: the node
2384: *
2385: * Is this node a Text node ?
1.36 daniel 2386: * Returns 1 yes, 0 no
1.21 daniel 2387: */
1.28 daniel 2388: int
2389: xmlNodeIsText(xmlNodePtr node) {
1.21 daniel 2390: if (node == NULL) return(0);
2391:
1.23 daniel 2392: if (node->type == XML_TEXT_NODE) return(1);
1.21 daniel 2393: return(0);
2394: }
2395:
1.23 daniel 2396: /**
1.36 daniel 2397: * xmlTextConcat:
1.23 daniel 2398: * @node: the node
2399: * @content: the content
2400: * @len: @content lenght
2401: *
2402: * Concat the given string at the end of the existing node content
1.21 daniel 2403: */
1.23 daniel 2404:
1.28 daniel 2405: void
2406: xmlTextConcat(xmlNodePtr node, const CHAR *content, int len) {
1.21 daniel 2407: if (node == NULL) return;
2408:
1.23 daniel 2409: if (node->type != XML_TEXT_NODE) {
1.21 daniel 2410: fprintf(stderr, "xmlTextConcat: node is not text\n");
2411: return;
2412: }
2413: node->content = xmlStrncat(node->content, content, len);
2414: }
2415:
1.1 veillard 2416: /************************************************************************
2417: * *
1.8 veillard 2418: * Output : to a FILE or in memory *
1.1 veillard 2419: * *
2420: ************************************************************************/
2421:
1.38 daniel 2422: #define BASE_BUFFER_SIZE 4000
1.8 veillard 2423:
1.23 daniel 2424: /**
1.38 daniel 2425: * xmlBufferCreate:
2426: *
2427: * routine to create an XML buffer.
2428: * returns the new structure.
2429: */
2430: xmlBufferPtr
2431: xmlBufferCreate(void) {
2432: xmlBufferPtr ret;
2433:
1.57 ! daniel 2434: ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
1.38 daniel 2435: if (ret == NULL) {
2436: fprintf(stderr, "xmlBufferCreate : out of memory!\n");
2437: return(NULL);
2438: }
2439: ret->use = 0;
2440: ret->size = BASE_BUFFER_SIZE;
1.57 ! daniel 2441: ret->content = (CHAR *) xmlMalloc(ret->size * sizeof(CHAR));
1.38 daniel 2442: if (ret->content == NULL) {
2443: fprintf(stderr, "xmlBufferCreate : out of memory!\n");
1.57 ! daniel 2444: xmlFree(ret);
1.38 daniel 2445: return(NULL);
2446: }
2447: ret->content[0] = 0;
2448: return(ret);
2449: }
2450:
2451: /**
2452: * xmlBufferFree:
2453: * @buf: the buffer to free
2454: *
2455: * Frees an XML buffer.
2456: */
2457: void
2458: xmlBufferFree(xmlBufferPtr buf) {
2459: if (buf == NULL) {
2460: fprintf(stderr, "xmlBufferFree: buf == NULL\n");
2461: return;
2462: }
2463: if (buf->content == NULL) {
2464: fprintf(stderr, "xmlBufferFree: buf->content == NULL\n");
2465: } else {
2466: memset(buf->content, -1, BASE_BUFFER_SIZE);
1.57 ! daniel 2467: xmlFree(buf->content);
1.38 daniel 2468: }
2469: memset(buf, -1, sizeof(xmlBuffer));
1.57 ! daniel 2470: xmlFree(buf);
1.38 daniel 2471: }
2472:
2473: /**
1.47 daniel 2474: * xmlBufferEmpty:
2475: * @buf: the buffer
2476: *
2477: * empty a buffer.
2478: */
2479: void
2480: xmlBufferEmpty(xmlBufferPtr buf) {
2481: buf->use = 0;
2482: memset(buf->content, -1, buf->size);/* just for debug */
2483: }
2484:
2485: /**
2486: * xmlBufferShrink:
2487: * @buf: the buffer to dump
2488: * @len: the number of CHAR to remove
2489: *
2490: * Remove the beginning of an XML buffer.
2491: *
2492: * Returns the number of CHAR removed, or -1 in case of failure.
2493: */
2494: int
2495: xmlBufferShrink(xmlBufferPtr buf, int len) {
2496: if (len == 0) return(0);
2497: if (len > buf->use) return(-1);
2498:
2499: buf->use -= len;
2500: memmove(buf->content, &buf->content[len], buf->use * sizeof(CHAR));
2501:
2502: buf->content[buf->use] = 0;
2503: return(len);
2504: }
2505:
2506: /**
1.38 daniel 2507: * xmlBufferDump:
2508: * @file: the file output
2509: * @buf: the buffer to dump
2510: *
2511: * Dumps an XML buffer to a FILE *.
2512: * Returns the number of CHAR written
2513: */
2514: int
2515: xmlBufferDump(FILE *file, xmlBufferPtr buf) {
2516: int ret;
2517:
2518: if (buf == NULL) {
2519: fprintf(stderr, "xmlBufferDump: buf == NULL\n");
2520: return(0);
2521: }
2522: if (buf->content == NULL) {
2523: fprintf(stderr, "xmlBufferDump: buf->content == NULL\n");
2524: return(0);
2525: }
2526: if (file == NULL) file = stdout;
2527: ret = fwrite(buf->content, sizeof(CHAR), buf->use, file);
2528: return(ret);
2529: }
2530:
2531: /**
2532: * xmlBufferAdd:
2533: * @buf: the buffer to dump
2534: * @str: the CHAR string
2535: * @len: the number of CHAR to add
2536: *
2537: * Add a string range to an XML buffer.
2538: */
2539: void
2540: xmlBufferAdd(xmlBufferPtr buf, const CHAR *str, int len) {
1.47 daniel 2541: int l;
1.38 daniel 2542:
2543: if (str == NULL) {
2544: fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2545: return;
2546: }
1.47 daniel 2547: l = xmlStrlen(str);
2548: if (l < len) len = l;
2549: if (len <= 0) return;
2550:
2551: if (buf->use + len + 10 >= buf->size) {
2552: CHAR *rebuf;
2553:
2554: buf->size *= 2;
2555: if (buf->use + len + 10 > buf->size)
2556: buf->size = buf->use + len + 10;
1.57 ! daniel 2557: rebuf = (CHAR *) xmlRealloc(buf->content, buf->size * sizeof(CHAR));
1.47 daniel 2558: if (rebuf == NULL) {
2559: fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2560: return;
1.38 daniel 2561: }
1.47 daniel 2562: buf->content = rebuf;
1.38 daniel 2563: }
1.47 daniel 2564: memmove(&buf->content[buf->use], str, len);
2565: buf->use += len;
2566: buf->content[buf->use] = 0;
1.38 daniel 2567: }
2568:
2569: /**
2570: * xmlBufferCat:
2571: * @buf: the buffer to dump
2572: * @str: the CHAR string
1.23 daniel 2573: *
1.38 daniel 2574: * Append a zero terminated string to an XML buffer.
1.23 daniel 2575: */
1.28 daniel 2576: void
1.38 daniel 2577: xmlBufferCat(xmlBufferPtr buf, const CHAR *str) {
1.8 veillard 2578: const CHAR *cur;
2579:
1.38 daniel 2580: if (str == NULL) {
2581: fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2582: return;
2583: }
2584: for (cur = str;*cur != 0;cur++) {
2585: if (buf->use + 10 >= buf->size) {
2586: CHAR *rebuf;
2587:
2588: buf->size *= 2;
1.57 ! daniel 2589: rebuf = (CHAR *) xmlRealloc(buf->content, buf->size * sizeof(CHAR));
1.38 daniel 2590: if (rebuf == NULL) {
2591: fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2592: return;
1.8 veillard 2593: }
1.38 daniel 2594: buf->content = rebuf;
1.8 veillard 2595: }
1.38 daniel 2596: buf->content[buf->use++] = *cur;
1.8 veillard 2597: }
2598: }
2599:
1.23 daniel 2600: /**
1.38 daniel 2601: * xmlBufferCCat:
2602: * @buf: the buffer to dump
2603: * @str: the C char string
1.23 daniel 2604: *
1.38 daniel 2605: * Append a zero terminated C string to an XML buffer.
1.23 daniel 2606: */
1.28 daniel 2607: void
1.38 daniel 2608: xmlBufferCCat(xmlBufferPtr buf, const char *str) {
1.21 daniel 2609: const char *cur;
1.8 veillard 2610:
1.38 daniel 2611: if (str == NULL) {
2612: fprintf(stderr, "xmlBufferAdd: str == NULL\n");
2613: return;
2614: }
2615: for (cur = str;*cur != 0;cur++) {
2616: if (buf->use + 10 >= buf->size) {
2617: CHAR *rebuf;
2618:
2619: buf->size *= 2;
1.57 ! daniel 2620: rebuf = (CHAR *) xmlRealloc(buf->content, buf->size * sizeof(CHAR));
1.38 daniel 2621: if (rebuf == NULL) {
2622: fprintf(stderr, "xmlBufferAdd : out of memory!\n");
2623: return;
1.8 veillard 2624: }
1.38 daniel 2625: buf->content = rebuf;
1.8 veillard 2626: }
1.38 daniel 2627: buf->content[buf->use++] = *cur;
1.8 veillard 2628: }
2629: }
2630:
1.23 daniel 2631: /**
1.38 daniel 2632: * xmlBufferWriteCHAR:
2633: * @buf: the XML buffer
2634: * @string: the string to add
2635: *
2636: * routine which manage and grows an output buffer. This one add
2637: * CHARs at the end of the buffer.
2638: */
2639: void
2640: xmlBufferWriteCHAR(xmlBufferPtr buf, const CHAR *string) {
2641: xmlBufferCat(buf, string);
2642: }
2643:
2644: /**
2645: * xmlBufferWriteChar:
1.42 daniel 2646: * @buf: the XML buffer output
1.38 daniel 2647: * @string: the string to add
2648: *
2649: * routine which manage and grows an output buffer. This one add
2650: * C chars at the end of the array.
2651: */
2652: void
2653: xmlBufferWriteChar(xmlBufferPtr buf, const char *string) {
2654: xmlBufferCCat(buf, string);
2655: }
2656:
2657:
2658: /**
1.43 daniel 2659: * xmlBufferWriteQuotedString:
2660: * @buf: the XML buffer output
2661: * @string: the string to add
2662: *
2663: * routine which manage and grows an output buffer. This one writes
2664: * a quoted or double quoted CHAR string, checking first if it holds
2665: * quote or double-quotes internally
2666: */
2667: void
2668: xmlBufferWriteQuotedString(xmlBufferPtr buf, const CHAR *string) {
1.53 daniel 2669: if (xmlStrchr(string, '"')) {
2670: if (xmlStrchr(string, '\'')) {
1.43 daniel 2671: fprintf(stderr,
2672: "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n");
2673: }
2674: xmlBufferCCat(buf, "'");
2675: xmlBufferCat(buf, string);
2676: xmlBufferCCat(buf, "'");
2677: } else {
2678: xmlBufferCCat(buf, "\"");
2679: xmlBufferCat(buf, string);
2680: xmlBufferCCat(buf, "\"");
2681: }
2682: }
2683:
2684:
2685: /**
1.23 daniel 2686: * xmlGlobalNsDump:
1.42 daniel 2687: * @buf: the XML buffer output
1.23 daniel 2688: * @cur: a namespace
2689: *
2690: * Dump a global Namespace, this is the old version based on PIs.
1.1 veillard 2691: */
1.28 daniel 2692: static void
1.38 daniel 2693: xmlGlobalNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.1 veillard 2694: if (cur == NULL) {
1.19 daniel 2695: fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
1.1 veillard 2696: return;
2697: }
1.19 daniel 2698: if (cur->type == XML_GLOBAL_NAMESPACE) {
1.38 daniel 2699: xmlBufferWriteChar(buf, "<?namespace");
1.12 daniel 2700: if (cur->href != NULL) {
1.43 daniel 2701: xmlBufferWriteChar(buf, " href=");
2702: xmlBufferWriteQuotedString(buf, cur->href);
1.12 daniel 2703: }
1.16 daniel 2704: if (cur->prefix != NULL) {
1.43 daniel 2705: xmlBufferWriteChar(buf, " AS=");
2706: xmlBufferWriteQuotedString(buf, cur->prefix);
1.12 daniel 2707: }
1.38 daniel 2708: xmlBufferWriteChar(buf, "?>\n");
1.19 daniel 2709: }
2710: }
2711:
1.23 daniel 2712: /**
2713: * xmlGlobalNsListDump:
1.42 daniel 2714: * @buf: the XML buffer output
1.23 daniel 2715: * @cur: the first namespace
2716: *
2717: * Dump a list of global Namespace, this is the old version based on PIs.
1.19 daniel 2718: */
1.28 daniel 2719: static void
1.38 daniel 2720: xmlGlobalNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19 daniel 2721: while (cur != NULL) {
1.38 daniel 2722: xmlGlobalNsDump(buf, cur);
1.19 daniel 2723: cur = cur->next;
2724: }
2725: }
2726:
1.23 daniel 2727: /**
2728: * xmlNsDump:
1.42 daniel 2729: * @buf: the XML buffer output
1.23 daniel 2730: * @cur: a namespace
2731: *
1.19 daniel 2732: * Dump a local Namespace definition.
1.23 daniel 2733: * Should be called in the context of attributes dumps.
1.19 daniel 2734: */
1.28 daniel 2735: static void
1.38 daniel 2736: xmlNsDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19 daniel 2737: if (cur == NULL) {
2738: fprintf(stderr, "xmlNsDump : Ns == NULL\n");
2739: return;
2740: }
2741: if (cur->type == XML_LOCAL_NAMESPACE) {
2742: /* Within the context of an element attributes */
1.16 daniel 2743: if (cur->prefix != NULL) {
1.38 daniel 2744: xmlBufferWriteChar(buf, " xmlns:");
2745: xmlBufferWriteCHAR(buf, cur->prefix);
1.19 daniel 2746: } else
1.38 daniel 2747: xmlBufferWriteChar(buf, " xmlns");
1.43 daniel 2748: xmlBufferWriteChar(buf, "=");
2749: xmlBufferWriteQuotedString(buf, cur->href);
1.19 daniel 2750: }
2751: }
2752:
1.23 daniel 2753: /**
2754: * xmlNsListDump:
1.42 daniel 2755: * @buf: the XML buffer output
1.23 daniel 2756: * @cur: the first namespace
2757: *
2758: * Dump a list of local Namespace definitions.
2759: * Should be called in the context of attributes dumps.
1.19 daniel 2760: */
1.28 daniel 2761: static void
1.38 daniel 2762: xmlNsListDump(xmlBufferPtr buf, xmlNsPtr cur) {
1.19 daniel 2763: while (cur != NULL) {
1.38 daniel 2764: xmlNsDump(buf, cur);
1.19 daniel 2765: cur = cur->next;
1.8 veillard 2766: }
1.1 veillard 2767: }
2768:
1.23 daniel 2769: /**
2770: * xmlDtdDump:
1.42 daniel 2771: * @buf: the XML buffer output
1.23 daniel 2772: * @doc: the document
2773: *
2774: * Dump the XML document DTD, if any.
1.17 daniel 2775: */
1.28 daniel 2776: static void
1.38 daniel 2777: xmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
1.31 daniel 2778: xmlDtdPtr cur = doc->intSubset;
1.21 daniel 2779:
1.17 daniel 2780: if (cur == NULL) {
1.31 daniel 2781: fprintf(stderr, "xmlDtdDump : no internal subset\n");
1.17 daniel 2782: return;
2783: }
1.38 daniel 2784: xmlBufferWriteChar(buf, "<!DOCTYPE ");
2785: xmlBufferWriteCHAR(buf, cur->name);
1.17 daniel 2786: if (cur->ExternalID != NULL) {
1.43 daniel 2787: xmlBufferWriteChar(buf, " PUBLIC ");
2788: xmlBufferWriteQuotedString(buf, cur->ExternalID);
2789: xmlBufferWriteChar(buf, " ");
2790: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.17 daniel 2791: } else if (cur->SystemID != NULL) {
1.43 daniel 2792: xmlBufferWriteChar(buf, " SYSTEM ");
2793: xmlBufferWriteQuotedString(buf, cur->SystemID);
1.17 daniel 2794: }
1.34 daniel 2795: if ((cur->entities == NULL) && (cur->elements == NULL) &&
1.35 daniel 2796: (cur->attributes == NULL) && (cur->notations == NULL)) {
1.38 daniel 2797: xmlBufferWriteChar(buf, ">\n");
1.21 daniel 2798: return;
2799: }
1.38 daniel 2800: xmlBufferWriteChar(buf, " [\n");
1.21 daniel 2801: if (cur->entities != NULL)
1.38 daniel 2802: xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
1.35 daniel 2803: if (cur->notations != NULL)
1.38 daniel 2804: xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
1.33 daniel 2805: if (cur->elements != NULL)
1.38 daniel 2806: xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
1.34 daniel 2807: if (cur->attributes != NULL)
1.38 daniel 2808: xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
2809: xmlBufferWriteChar(buf, "]");
1.21 daniel 2810:
1.38 daniel 2811: xmlBufferWriteChar(buf, ">\n");
1.17 daniel 2812: }
2813:
1.23 daniel 2814: /**
2815: * xmlAttrDump:
1.42 daniel 2816: * @buf: the XML buffer output
1.23 daniel 2817: * @doc: the document
2818: * @cur: the attribute pointer
2819: *
2820: * Dump an XML attribute
1.1 veillard 2821: */
1.28 daniel 2822: static void
1.38 daniel 2823: xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
1.23 daniel 2824: CHAR *value;
1.1 veillard 2825:
2826: if (cur == NULL) {
1.20 daniel 2827: fprintf(stderr, "xmlAttrDump : property == NULL\n");
1.1 veillard 2828: return;
2829: }
1.38 daniel 2830: xmlBufferWriteChar(buf, " ");
1.56 daniel 2831: if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
2832: xmlBufferWriteCHAR(buf, cur->ns->prefix);
2833: xmlBufferWriteChar(buf, ":");
2834: }
1.38 daniel 2835: xmlBufferWriteCHAR(buf, cur->name);
1.24 daniel 2836: value = xmlNodeListGetString(doc, cur->val, 0);
1.23 daniel 2837: if (value) {
1.43 daniel 2838: xmlBufferWriteChar(buf, "=");
2839: xmlBufferWriteQuotedString(buf, value);
1.57 ! daniel 2840: xmlFree(value);
1.34 daniel 2841: } else {
1.38 daniel 2842: xmlBufferWriteChar(buf, "=\"\"");
1.3 veillard 2843: }
1.8 veillard 2844: }
2845:
1.23 daniel 2846: /**
2847: * xmlAttrListDump:
1.42 daniel 2848: * @buf: the XML buffer output
1.23 daniel 2849: * @doc: the document
2850: * @cur: the first attribute pointer
2851: *
2852: * Dump a list of XML attributes
1.8 veillard 2853: */
1.28 daniel 2854: static void
1.38 daniel 2855: xmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
1.8 veillard 2856: if (cur == NULL) {
1.20 daniel 2857: fprintf(stderr, "xmlAttrListDump : property == NULL\n");
1.1 veillard 2858: return;
2859: }
1.8 veillard 2860: while (cur != NULL) {
1.38 daniel 2861: xmlAttrDump(buf, doc, cur);
1.8 veillard 2862: cur = cur->next;
1.1 veillard 2863: }
2864: }
2865:
2866:
1.28 daniel 2867: static void
1.38 daniel 2868: xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level);
1.23 daniel 2869: /**
2870: * xmlNodeListDump:
1.42 daniel 2871: * @buf: the XML buffer output
1.23 daniel 2872: * @doc: the document
2873: * @cur: the first node
2874: * @level: the imbrication level for indenting
2875: *
2876: * Dump an XML node list, recursive behaviour,children are printed too.
2877: */
1.28 daniel 2878: static void
1.38 daniel 2879: xmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
1.25 daniel 2880: int needIndent = 0, i;
2881:
1.1 veillard 2882: if (cur == NULL) {
1.8 veillard 2883: fprintf(stderr, "xmlNodeListDump : node == NULL\n");
1.1 veillard 2884: return;
2885: }
1.8 veillard 2886: while (cur != NULL) {
1.25 daniel 2887: if ((cur->type != XML_TEXT_NODE) &&
2888: (cur->type != XML_ENTITY_REF_NODE)) {
2889: if (!needIndent) {
2890: needIndent = 1;
1.38 daniel 2891: xmlBufferWriteChar(buf, "\n");
1.25 daniel 2892: }
2893: }
1.38 daniel 2894: xmlNodeDump(buf, doc, cur, level);
1.8 veillard 2895: cur = cur->next;
1.3 veillard 2896: }
1.25 daniel 2897: if ((xmlIndentTreeOutput) && (needIndent))
2898: for (i = 1;i < level;i++)
1.38 daniel 2899: xmlBufferWriteChar(buf, " ");
1.1 veillard 2900: }
2901:
1.23 daniel 2902: /**
1.25 daniel 2903: * xmlNodeDump:
1.42 daniel 2904: * @buf: the XML buffer output
1.23 daniel 2905: * @doc: the document
2906: * @cur: the current node
2907: * @level: the imbrication level for indenting
2908: *
2909: * Dump an XML node, recursive behaviour,children are printed too.
1.1 veillard 2910: */
1.28 daniel 2911: static void
1.38 daniel 2912: xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
1.8 veillard 2913: int i;
2914:
1.1 veillard 2915: if (cur == NULL) {
1.8 veillard 2916: fprintf(stderr, "xmlNodeDump : node == NULL\n");
2917: return;
2918: }
1.23 daniel 2919: if (cur->type == XML_TEXT_NODE) {
1.45 daniel 2920: if (cur->content != NULL) {
2921: CHAR *buffer;
2922:
1.46 daniel 2923: buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
1.45 daniel 2924: if (buffer != NULL) {
2925: xmlBufferWriteCHAR(buf, buffer);
1.57 ! daniel 2926: xmlFree(buffer);
1.45 daniel 2927: }
2928: }
1.14 daniel 2929: return;
2930: }
1.52 daniel 2931: if (cur->type == XML_PI_NODE) {
2932: if (cur->content != NULL) {
2933: xmlBufferWriteChar(buf, "<?");
2934: xmlBufferWriteCHAR(buf, cur->name);
2935: if (cur->content != NULL) {
2936: xmlBufferWriteChar(buf, " ");
2937: xmlBufferWriteCHAR(buf, cur->content);
2938: }
2939: xmlBufferWriteChar(buf, "?>\n");
2940: }
2941: return;
2942: }
1.23 daniel 2943: if (cur->type == XML_COMMENT_NODE) {
1.14 daniel 2944: if (cur->content != NULL) {
1.38 daniel 2945: xmlBufferWriteChar(buf, "<!--");
2946: xmlBufferWriteCHAR(buf, cur->content);
1.53 daniel 2947: xmlBufferWriteChar(buf, "-->\n");
1.14 daniel 2948: }
1.8 veillard 2949: return;
2950: }
1.23 daniel 2951: if (cur->type == XML_ENTITY_REF_NODE) {
1.38 daniel 2952: xmlBufferWriteChar(buf, "&");
2953: xmlBufferWriteCHAR(buf, cur->name);
2954: xmlBufferWriteChar(buf, ";");
1.50 daniel 2955: return;
2956: }
2957: if (cur->type == XML_CDATA_SECTION_NODE) {
2958: xmlBufferWriteChar(buf, "<![CDATA[");
2959: if (cur->content != NULL)
2960: xmlBufferWriteCHAR(buf, cur->content);
2961: xmlBufferWriteChar(buf, "]]>");
1.23 daniel 2962: return;
2963: }
1.21 daniel 2964: if (xmlIndentTreeOutput)
2965: for (i = 0;i < level;i++)
1.38 daniel 2966: xmlBufferWriteChar(buf, " ");
1.8 veillard 2967:
1.38 daniel 2968: xmlBufferWriteChar(buf, "<");
1.16 daniel 2969: if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1.38 daniel 2970: xmlBufferWriteCHAR(buf, cur->ns->prefix);
2971: xmlBufferWriteChar(buf, ":");
1.8 veillard 2972: }
2973:
1.38 daniel 2974: xmlBufferWriteCHAR(buf, cur->name);
1.19 daniel 2975: if (cur->nsDef)
1.38 daniel 2976: xmlNsListDump(buf, cur->nsDef);
1.8 veillard 2977: if (cur->properties != NULL)
1.38 daniel 2978: xmlAttrListDump(buf, doc, cur->properties);
1.8 veillard 2979:
2980: if ((cur->content == NULL) && (cur->childs == NULL)) {
1.38 daniel 2981: xmlBufferWriteChar(buf, "/>\n");
1.1 veillard 2982: return;
2983: }
1.38 daniel 2984: xmlBufferWriteChar(buf, ">");
1.46 daniel 2985: if (cur->content != NULL) {
2986: CHAR *buffer;
2987:
2988: buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
2989: if (buffer != NULL) {
2990: xmlBufferWriteCHAR(buf, buffer);
1.57 ! daniel 2991: xmlFree(buffer);
1.46 daniel 2992: }
2993: }
1.8 veillard 2994: if (cur->childs != NULL) {
1.38 daniel 2995: xmlNodeListDump(buf, doc, cur->childs, level + 1);
1.8 veillard 2996: }
1.38 daniel 2997: xmlBufferWriteChar(buf, "</");
1.16 daniel 2998: if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1.38 daniel 2999: xmlBufferWriteCHAR(buf, cur->ns->prefix);
3000: xmlBufferWriteChar(buf, ":");
1.1 veillard 3001: }
1.8 veillard 3002:
1.38 daniel 3003: xmlBufferWriteCHAR(buf, cur->name);
3004: xmlBufferWriteChar(buf, ">\n");
1.1 veillard 3005: }
3006:
1.23 daniel 3007: /**
3008: * xmlDocContentDump:
1.42 daniel 3009: * @buf: the XML buffer output
1.23 daniel 3010: * @cur: the document
3011: *
3012: * Dump an XML document.
1.1 veillard 3013: */
1.28 daniel 3014: static void
1.38 daniel 3015: xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
1.46 daniel 3016: xmlBufferWriteChar(buf, "<?xml version=");
3017: if (cur->version != NULL)
3018: xmlBufferWriteQuotedString(buf, cur->version);
3019: else
3020: xmlBufferWriteChar(buf, "\"1.0\"");
1.15 daniel 3021: if (cur->encoding != NULL) {
1.43 daniel 3022: xmlBufferWriteChar(buf, " encoding=");
3023: xmlBufferWriteQuotedString(buf, cur->encoding);
1.15 daniel 3024: }
3025: switch (cur->standalone) {
3026: case 0:
1.38 daniel 3027: xmlBufferWriteChar(buf, " standalone=\"no\"");
1.15 daniel 3028: break;
3029: case 1:
1.38 daniel 3030: xmlBufferWriteChar(buf, " standalone=\"yes\"");
1.15 daniel 3031: break;
3032: }
1.38 daniel 3033: xmlBufferWriteChar(buf, "?>\n");
1.31 daniel 3034: if (cur->intSubset != NULL)
1.38 daniel 3035: xmlDtdDump(buf, cur);
1.19 daniel 3036: if (cur->root != NULL) {
1.52 daniel 3037: xmlNodePtr child = cur->root;
3038:
1.19 daniel 3039: /* global namespace definitions, the old way */
3040: if (oldXMLWDcompatibility)
1.38 daniel 3041: xmlGlobalNsListDump(buf, cur->oldNs);
1.19 daniel 3042: else
3043: xmlUpgradeOldNs(cur);
1.52 daniel 3044:
3045: while (child != NULL) {
3046: xmlNodeDump(buf, cur, child, 0);
3047: child = child->next;
3048: }
1.19 daniel 3049: }
3050: }
3051:
1.23 daniel 3052: /**
3053: * xmlDocDumpMemory:
3054: * @cur: the document
3055: * @mem: OUT: the memory pointer
3056: * @size: OUT: the memory lenght
3057: *
3058: * Dump an XML document in memory and return the CHAR * and it's size.
3059: * It's up to the caller to free the memory.
1.19 daniel 3060: */
1.28 daniel 3061: void
3062: xmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
1.38 daniel 3063: xmlBufferPtr buf;
3064:
1.19 daniel 3065: if (cur == NULL) {
1.31 daniel 3066: #ifdef DEBUG_TREE
3067: fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
3068: #endif
1.19 daniel 3069: *mem = NULL;
3070: *size = 0;
3071: return;
3072: }
1.38 daniel 3073: buf = xmlBufferCreate();
3074: if (buf == NULL) {
3075: *mem = NULL;
3076: *size = 0;
3077: return;
3078: }
3079: xmlDocContentDump(buf, cur);
1.51 daniel 3080: *mem = xmlStrndup(buf->content, buf->use);
1.38 daniel 3081: *size = buf->use;
1.51 daniel 3082: xmlBufferFree(buf);
1.1 veillard 3083: }
3084:
1.23 daniel 3085: /**
3086: * xmlGetDocCompressMode:
3087: * @doc: the document
3088: *
3089: * get the compression ratio for a document, ZLIB based
1.36 daniel 3090: * Returns 0 (uncompressed) to 9 (max compression)
1.23 daniel 3091: */
1.28 daniel 3092: int
3093: xmlGetDocCompressMode (xmlDocPtr doc) {
1.23 daniel 3094: if (doc == NULL) return(-1);
3095: return(doc->compression);
3096: }
3097:
3098: /**
3099: * xmlSetDocCompressMode:
3100: * @doc: the document
3101: * @mode: the compression ratio
3102: *
3103: * set the compression ratio for a document, ZLIB based
3104: * Correct values: 0 (uncompressed) to 9 (max compression)
3105: */
1.28 daniel 3106: void
3107: xmlSetDocCompressMode (xmlDocPtr doc, int mode) {
1.23 daniel 3108: if (doc == NULL) return;
3109: if (mode < 0) doc->compression = 0;
3110: else if (mode > 9) doc->compression = 9;
3111: else doc->compression = mode;
3112: }
3113:
3114: /**
3115: * xmlGetCompressMode:
3116: *
3117: * get the default compression mode used, ZLIB based.
1.36 daniel 3118: * Returns 0 (uncompressed) to 9 (max compression)
1.23 daniel 3119: */
1.28 daniel 3120: int
3121: xmlGetCompressMode(void) {
1.23 daniel 3122: return(xmlCompressMode);
3123: }
3124:
3125: /**
3126: * xmlSetCompressMode:
3127: * @mode: the compression ratio
3128: *
3129: * set the default compression mode used, ZLIB based
3130: * Correct values: 0 (uncompressed) to 9 (max compression)
1.1 veillard 3131: */
1.28 daniel 3132: void
3133: xmlSetCompressMode(int mode) {
1.23 daniel 3134: if (mode < 0) xmlCompressMode = 0;
3135: else if (mode > 9) xmlCompressMode = 9;
3136: else xmlCompressMode = mode;
3137: }
1.1 veillard 3138:
1.23 daniel 3139: /**
3140: * xmlDocDump:
3141: * @f: the FILE*
3142: * @cur: the document
3143: *
3144: * Dump an XML document to an open FILE.
3145: */
1.28 daniel 3146: void
3147: xmlDocDump(FILE *f, xmlDocPtr cur) {
1.38 daniel 3148: xmlBufferPtr buf;
3149:
1.1 veillard 3150: if (cur == NULL) {
1.31 daniel 3151: #ifdef DEBUG_TREE
1.1 veillard 3152: fprintf(stderr, "xmlDocDump : document == NULL\n");
1.31 daniel 3153: #endif
1.1 veillard 3154: return;
3155: }
1.38 daniel 3156: buf = xmlBufferCreate();
3157: if (buf == NULL) return;
3158: xmlDocContentDump(buf, cur);
3159: xmlBufferDump(f, buf);
3160: xmlBufferFree(buf);
1.23 daniel 3161: }
3162:
3163: /**
3164: * xmlSaveFile:
3165: * @filename: the filename
3166: * @cur: the document
3167: *
3168: * Dump an XML document to a file. Will use compression if
3169: * compiled in and enabled.
3170: * returns: the number of file written or -1 in case of failure.
3171: */
1.28 daniel 3172: int
3173: xmlSaveFile(const char *filename, xmlDocPtr cur) {
1.38 daniel 3174: xmlBufferPtr buf;
1.23 daniel 3175: #ifdef HAVE_ZLIB_H
3176: gzFile zoutput = NULL;
3177: char mode[15];
3178: #endif
1.24 daniel 3179: FILE *output = NULL;
1.23 daniel 3180: int ret;
3181:
1.38 daniel 3182: /*
3183: * save the content to a temp buffer.
3184: */
3185: buf = xmlBufferCreate();
3186: if (buf == NULL) return(0);
3187: xmlDocContentDump(buf, cur);
3188:
1.23 daniel 3189: #ifdef HAVE_ZLIB_H
3190: if ((cur->compression > 0) && (cur->compression <= 9)) {
3191: sprintf(mode, "w%d", cur->compression);
3192: zoutput = gzopen(filename, mode);
3193: }
3194: if (zoutput == NULL) {
3195: #endif
3196: output = fopen(filename, "w");
3197: if (output == NULL) return(-1);
3198: #ifdef HAVE_ZLIB_H
3199: }
3200:
3201: if (zoutput != NULL) {
1.38 daniel 3202: ret = gzwrite(zoutput, buf->content, sizeof(CHAR) * buf->use);
1.23 daniel 3203: gzclose(zoutput);
1.38 daniel 3204: } else {
3205: #endif
3206: ret = xmlBufferDump(output, buf);
3207: fclose(output);
3208: #ifdef HAVE_ZLIB_H
1.23 daniel 3209: }
3210: #endif
1.41 daniel 3211: xmlBufferFree(buf);
1.23 daniel 3212: return(ret * sizeof(CHAR));
1.1 veillard 3213: }
3214:
Webmaster