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