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