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