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