ReactOS 0.4.15-dev-7934-g1dc8d80
xmlsave.c
Go to the documentation of this file.
1/*
2 * xmlsave.c: Implementation of the document serializer
3 *
4 * See Copyright for the status of this software.
5 *
6 * daniel@veillard.com
7 */
8
9#define IN_LIBXML
10#include "libxml.h"
11
12#include <string.h>
13#include <libxml/xmlmemory.h>
15#include <libxml/tree.h>
16#include <libxml/xmlsave.h>
17
18#define MAX_INDENT 60
19
20#include <libxml/HTMLtree.h>
21
22#include "buf.h"
23#include "enc.h"
24#include "save.h"
25
26/************************************************************************
27 * *
28 * XHTML detection *
29 * *
30 ************************************************************************/
31#define XHTML_STRICT_PUBLIC_ID BAD_CAST \
32 "-//W3C//DTD XHTML 1.0 Strict//EN"
33#define XHTML_STRICT_SYSTEM_ID BAD_CAST \
34 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
35#define XHTML_FRAME_PUBLIC_ID BAD_CAST \
36 "-//W3C//DTD XHTML 1.0 Frameset//EN"
37#define XHTML_FRAME_SYSTEM_ID BAD_CAST \
38 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
39#define XHTML_TRANS_PUBLIC_ID BAD_CAST \
40 "-//W3C//DTD XHTML 1.0 Transitional//EN"
41#define XHTML_TRANS_SYSTEM_ID BAD_CAST \
42 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
43
44#define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml"
54int
55xmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID) {
56 if ((systemID == NULL) && (publicID == NULL))
57 return(-1);
58 if (publicID != NULL) {
59 if (xmlStrEqual(publicID, XHTML_STRICT_PUBLIC_ID)) return(1);
60 if (xmlStrEqual(publicID, XHTML_FRAME_PUBLIC_ID)) return(1);
61 if (xmlStrEqual(publicID, XHTML_TRANS_PUBLIC_ID)) return(1);
62 }
63 if (systemID != NULL) {
64 if (xmlStrEqual(systemID, XHTML_STRICT_SYSTEM_ID)) return(1);
65 if (xmlStrEqual(systemID, XHTML_FRAME_SYSTEM_ID)) return(1);
66 if (xmlStrEqual(systemID, XHTML_TRANS_SYSTEM_ID)) return(1);
67 }
68 return(0);
69}
70
71#ifdef LIBXML_OUTPUT_ENABLED
72
73#define TODO \
74 xmlGenericError(xmlGenericErrorContext, \
75 "Unimplemented block at %s:%d\n", \
76 __FILE__, __LINE__);
77
78struct _xmlSaveCtxt {
79 void *_private;
80 int type;
81 int fd;
82 const xmlChar *filename;
83 const xmlChar *encoding;
86 int options;
87 int level;
88 int format;
89 char indent[MAX_INDENT + 1]; /* array for indenting output */
90 int indent_nr;
91 int indent_size;
92 xmlCharEncodingOutputFunc escape; /* used for element content */
93 xmlCharEncodingOutputFunc escapeAttr;/* used for attribute content */
94};
95
96/************************************************************************
97 * *
98 * Output error handlers *
99 * *
100 ************************************************************************/
107static void
108xmlSaveErrMemory(const char *extra)
109{
110 __xmlSimpleError(XML_FROM_OUTPUT, XML_ERR_NO_MEMORY, NULL, NULL, extra);
111}
112
121static void
122xmlSaveErr(int code, xmlNodePtr node, const char *extra)
123{
124 const char *msg = NULL;
125
126 switch(code) {
128 msg = "string is not in UTF-8\n";
129 break;
131 msg = "invalid character value\n";
132 break;
134 msg = "unknown encoding %s\n";
135 break;
137 msg = "document has no DOCTYPE\n";
138 break;
139 default:
140 msg = "unexpected error number\n";
141 }
142 __xmlSimpleError(XML_FROM_OUTPUT, code, node, msg, extra);
143}
144
145/************************************************************************
146 * *
147 * Special escaping routines *
148 * *
149 ************************************************************************/
150static unsigned char *
151xmlSerializeHexCharRef(unsigned char *out, int val) {
152 unsigned char *ptr;
153
154 *out++ = '&';
155 *out++ = '#';
156 *out++ = 'x';
157 if (val < 0x10) ptr = out;
158 else if (val < 0x100) ptr = out + 1;
159 else if (val < 0x1000) ptr = out + 2;
160 else if (val < 0x10000) ptr = out + 3;
161 else if (val < 0x100000) ptr = out + 4;
162 else ptr = out + 5;
163 out = ptr + 1;
164 while (val > 0) {
165 switch (val & 0xF) {
166 case 0: *ptr-- = '0'; break;
167 case 1: *ptr-- = '1'; break;
168 case 2: *ptr-- = '2'; break;
169 case 3: *ptr-- = '3'; break;
170 case 4: *ptr-- = '4'; break;
171 case 5: *ptr-- = '5'; break;
172 case 6: *ptr-- = '6'; break;
173 case 7: *ptr-- = '7'; break;
174 case 8: *ptr-- = '8'; break;
175 case 9: *ptr-- = '9'; break;
176 case 0xA: *ptr-- = 'A'; break;
177 case 0xB: *ptr-- = 'B'; break;
178 case 0xC: *ptr-- = 'C'; break;
179 case 0xD: *ptr-- = 'D'; break;
180 case 0xE: *ptr-- = 'E'; break;
181 case 0xF: *ptr-- = 'F'; break;
182 default: *ptr-- = '0'; break;
183 }
184 val >>= 4;
185 }
186 *out++ = ';';
187 *out = 0;
188 return(out);
189}
190
206static int
207xmlEscapeEntities(unsigned char* out, int *outlen,
208 const xmlChar* in, int *inlen) {
209 unsigned char* outstart = out;
210 const unsigned char* base = in;
211 unsigned char* outend = out + *outlen;
212 const unsigned char* inend;
213 int val;
214
215 inend = in + (*inlen);
216
217 while ((in < inend) && (out < outend)) {
218 if (*in == '<') {
219 if (outend - out < 4) break;
220 *out++ = '&';
221 *out++ = 'l';
222 *out++ = 't';
223 *out++ = ';';
224 in++;
225 continue;
226 } else if (*in == '>') {
227 if (outend - out < 4) break;
228 *out++ = '&';
229 *out++ = 'g';
230 *out++ = 't';
231 *out++ = ';';
232 in++;
233 continue;
234 } else if (*in == '&') {
235 if (outend - out < 5) break;
236 *out++ = '&';
237 *out++ = 'a';
238 *out++ = 'm';
239 *out++ = 'p';
240 *out++ = ';';
241 in++;
242 continue;
243 } else if (((*in >= 0x20) && (*in < 0x80)) ||
244 (*in == '\n') || (*in == '\t')) {
245 /*
246 * default case, just copy !
247 */
248 *out++ = *in++;
249 continue;
250 } else if (*in >= 0x80) {
251 /*
252 * We assume we have UTF-8 input.
253 */
254 if (outend - out < 11) break;
255
256 if (*in < 0xC0) {
257 xmlSaveErr(XML_SAVE_NOT_UTF8, NULL, NULL);
258 in++;
259 goto error;
260 } else if (*in < 0xE0) {
261 if (inend - in < 2) break;
262 val = (in[0]) & 0x1F;
263 val <<= 6;
264 val |= (in[1]) & 0x3F;
265 in += 2;
266 } else if (*in < 0xF0) {
267 if (inend - in < 3) break;
268 val = (in[0]) & 0x0F;
269 val <<= 6;
270 val |= (in[1]) & 0x3F;
271 val <<= 6;
272 val |= (in[2]) & 0x3F;
273 in += 3;
274 } else if (*in < 0xF8) {
275 if (inend - in < 4) break;
276 val = (in[0]) & 0x07;
277 val <<= 6;
278 val |= (in[1]) & 0x3F;
279 val <<= 6;
280 val |= (in[2]) & 0x3F;
281 val <<= 6;
282 val |= (in[3]) & 0x3F;
283 in += 4;
284 } else {
285 xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL);
286 in++;
287 goto error;
288 }
289 if (!IS_CHAR(val)) {
290 xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL);
291 in++;
292 goto error;
293 }
294
295 /*
296 * We could do multiple things here. Just save as a char ref
297 */
298 out = xmlSerializeHexCharRef(out, val);
299 } else if (IS_BYTE_CHAR(*in)) {
300 if (outend - out < 6) break;
301 out = xmlSerializeHexCharRef(out, *in++);
302 } else {
304 "xmlEscapeEntities : char out of range\n");
305 in++;
306 goto error;
307 }
308 }
309 *outlen = out - outstart;
310 *inlen = in - base;
311 return(0);
312error:
313 *outlen = out - outstart;
314 *inlen = in - base;
315 return(-1);
316}
317
318/************************************************************************
319 * *
320 * Allocation and deallocation *
321 * *
322 ************************************************************************/
329static void
330xmlSaveCtxtInit(xmlSaveCtxtPtr ctxt)
331{
332 int i;
333 int len;
334
335 if (ctxt == NULL) return;
336 if ((ctxt->encoding == NULL) && (ctxt->escape == NULL))
337 ctxt->escape = xmlEscapeEntities;
339 if ((xmlTreeIndentString == NULL) || (len == 0)) {
340 memset(&ctxt->indent[0], 0, MAX_INDENT + 1);
341 } else {
342 ctxt->indent_size = len;
343 ctxt->indent_nr = MAX_INDENT / ctxt->indent_size;
344 for (i = 0;i < ctxt->indent_nr;i++)
345 memcpy(&ctxt->indent[i * ctxt->indent_size], xmlTreeIndentString,
346 ctxt->indent_size);
347 ctxt->indent[ctxt->indent_nr * ctxt->indent_size] = 0;
348 }
349
350 if (xmlSaveNoEmptyTags) {
351 ctxt->options |= XML_SAVE_NO_EMPTY;
352 }
353}
354
360static void
361xmlFreeSaveCtxt(xmlSaveCtxtPtr ctxt)
362{
363 if (ctxt == NULL) return;
364 if (ctxt->encoding != NULL)
365 xmlFree((char *) ctxt->encoding);
366 if (ctxt->buf != NULL)
367 xmlOutputBufferClose(ctxt->buf);
368 xmlFree(ctxt);
369}
370
378static xmlSaveCtxtPtr
379xmlNewSaveCtxt(const char *encoding, int options)
380{
381 xmlSaveCtxtPtr ret;
382
383 ret = (xmlSaveCtxtPtr) xmlMalloc(sizeof(xmlSaveCtxt));
384 if (ret == NULL) {
385 xmlSaveErrMemory("creating saving context");
386 return ( NULL );
387 }
388 memset(ret, 0, sizeof(xmlSaveCtxt));
389
390 if (encoding != NULL) {
392 if (ret->handler == NULL) {
394 xmlFreeSaveCtxt(ret);
395 return(NULL);
396 }
397 ret->encoding = xmlStrdup((const xmlChar *)encoding);
398 ret->escape = NULL;
399 }
400 xmlSaveCtxtInit(ret);
401
402 /*
403 * Use the options
404 */
405
406 /* Re-check this option as it may already have been set */
407 if ((ret->options & XML_SAVE_NO_EMPTY) && ! (options & XML_SAVE_NO_EMPTY)) {
408 options |= XML_SAVE_NO_EMPTY;
409 }
410
411 ret->options = options;
412 if (options & XML_SAVE_FORMAT)
413 ret->format = 1;
414 else if (options & XML_SAVE_WSNONSIG)
415 ret->format = 2;
416
417 return(ret);
418}
419
420/************************************************************************
421 * *
422 * Dumping XML tree content to a simple buffer *
423 * *
424 ************************************************************************/
433static void
434xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr)
435{
436 xmlNodePtr children;
437
438 children = attr->children;
439 while (children != NULL) {
440 switch (children->type) {
441 case XML_TEXT_NODE:
442 xmlBufAttrSerializeTxtContent(buf->buffer, attr->doc,
443 attr, children->content);
444 break;
446 xmlBufAdd(buf->buffer, BAD_CAST "&", 1);
447 xmlBufAdd(buf->buffer, children->name,
448 xmlStrlen(children->name));
449 xmlBufAdd(buf->buffer, BAD_CAST ";", 1);
450 break;
451 default:
452 /* should not happen unless we have a badly built tree */
453 break;
454 }
455 children = children->next;
456 }
457}
458
466void
467xmlBufDumpNotationTable(xmlBufPtr buf, xmlNotationTablePtr table) {
469
471 if (buffer == NULL) {
472 /*
473 * TODO set the error in buf
474 */
475 return;
476 }
478 xmlDumpNotationTable(buffer, table);
480}
481
490void
491xmlBufDumpElementDecl(xmlBufPtr buf, xmlElementPtr elem) {
493
495 if (buffer == NULL) {
496 /*
497 * TODO set the error in buf
498 */
499 return;
500 }
502 xmlDumpElementDecl(buffer, elem);
504}
505
514void
515xmlBufDumpAttributeDecl(xmlBufPtr buf, xmlAttributePtr attr) {
517
519 if (buffer == NULL) {
520 /*
521 * TODO set the error in buf
522 */
523 return;
524 }
526 xmlDumpAttributeDecl(buffer, attr);
528}
529
537void
538xmlBufDumpEntityDecl(xmlBufPtr buf, xmlEntityPtr ent) {
540
542 if (buffer == NULL) {
543 /*
544 * TODO set the error in buf
545 */
546 return;
547 }
549 xmlDumpEntityDecl(buffer, ent);
551}
552
553/************************************************************************
554 * *
555 * Dumping XML tree content to an I/O output buffer *
556 * *
557 ************************************************************************/
558
559static int xmlSaveSwitchEncoding(xmlSaveCtxtPtr ctxt, const char *encoding) {
560 xmlOutputBufferPtr buf = ctxt->buf;
561
562 if ((encoding != NULL) && (buf->encoder == NULL) && (buf->conv == NULL)) {
563 buf->encoder = xmlFindCharEncodingHandler((const char *)encoding);
564 if (buf->encoder == NULL) {
566 (const char *)encoding);
567 return(-1);
568 }
569 buf->conv = xmlBufCreate();
570 if (buf->conv == NULL) {
571 xmlCharEncCloseFunc(buf->encoder);
572 xmlSaveErrMemory("creating encoding buffer");
573 return(-1);
574 }
575 /*
576 * initialize the state, e.g. if outputting a BOM
577 */
579 }
580 return(0);
581}
582
583static int xmlSaveClearEncoding(xmlSaveCtxtPtr ctxt) {
584 xmlOutputBufferPtr buf = ctxt->buf;
585 xmlOutputBufferFlush(buf);
586 xmlCharEncCloseFunc(buf->encoder);
587 xmlBufFree(buf->conv);
588 buf->encoder = NULL;
589 buf->conv = NULL;
590 return(0);
591}
592
593#ifdef LIBXML_HTML_ENABLED
594static void
595xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
596#endif
597static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
598void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur);
599static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur);
600
608static void
609xmlOutputBufferWriteWSNonSig(xmlSaveCtxtPtr ctxt, int extra)
610{
611 int i;
612 if ((ctxt == NULL) || (ctxt->buf == NULL))
613 return;
614 xmlOutputBufferWrite(ctxt->buf, 1, "\n");
615 for (i = 0; i < (ctxt->level + extra); i += ctxt->indent_nr) {
616 xmlOutputBufferWrite(ctxt->buf, ctxt->indent_size *
617 ((ctxt->level + extra - i) > ctxt->indent_nr ?
618 ctxt->indent_nr : (ctxt->level + extra - i)),
619 ctxt->indent);
620 }
621}
622
633static void
634xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur, xmlSaveCtxtPtr ctxt) {
635 if ((cur == NULL) || (buf == NULL)) return;
636 if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) {
637 if (xmlStrEqual(cur->prefix, BAD_CAST "xml"))
638 return;
639
640 if (ctxt != NULL && ctxt->format == 2)
641 xmlOutputBufferWriteWSNonSig(ctxt, 2);
642 else
643 xmlOutputBufferWrite(buf, 1, " ");
644
645 /* Within the context of an element attributes */
646 if (cur->prefix != NULL) {
647 xmlOutputBufferWrite(buf, 6, "xmlns:");
648 xmlOutputBufferWriteString(buf, (const char *)cur->prefix);
649 } else
650 xmlOutputBufferWrite(buf, 5, "xmlns");
651 xmlOutputBufferWrite(buf, 1, "=");
652 xmlBufWriteQuotedString(buf->buffer, cur->href);
653 }
654}
655
664static void
665xmlNsDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
666 xmlNsDumpOutput(ctxt->buf, cur, ctxt);
667}
668
677static void
678xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
679 while (cur != NULL) {
680 xmlNsDumpOutput(ctxt->buf, cur, ctxt);
681 cur = cur->next;
682 }
683}
684
693void
694xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
695 while (cur != NULL) {
696 xmlNsDumpOutput(buf, cur, NULL);
697 cur = cur->next;
698 }
699}
700
708static void
709xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
712 int format, level;
713
714 if (dtd == NULL) return;
715 if ((ctxt == NULL) || (ctxt->buf == NULL))
716 return;
717 buf = ctxt->buf;
718 xmlOutputBufferWrite(buf, 10, "<!DOCTYPE ");
719 xmlOutputBufferWriteString(buf, (const char *)dtd->name);
720 if (dtd->ExternalID != NULL) {
721 xmlOutputBufferWrite(buf, 8, " PUBLIC ");
723 xmlOutputBufferWrite(buf, 1, " ");
724 xmlBufWriteQuotedString(buf->buffer, dtd->SystemID);
725 } else if (dtd->SystemID != NULL) {
726 xmlOutputBufferWrite(buf, 8, " SYSTEM ");
727 xmlBufWriteQuotedString(buf->buffer, dtd->SystemID);
728 }
729 if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
730 (dtd->attributes == NULL) && (dtd->notations == NULL) &&
731 (dtd->pentities == NULL)) {
732 xmlOutputBufferWrite(buf, 1, ">");
733 return;
734 }
735 xmlOutputBufferWrite(buf, 3, " [\n");
736 /*
737 * Dump the notations first they are not in the DTD children list
738 * Do this only on a standalone DTD or on the internal subset though.
739 */
740 if ((dtd->notations != NULL) && ((dtd->doc == NULL) ||
741 (dtd->doc->intSubset == dtd))) {
742 xmlBufDumpNotationTable(buf->buffer,
744 }
745 format = ctxt->format;
746 level = ctxt->level;
747 ctxt->format = 0;
748 ctxt->level = -1;
749 for (cur = dtd->children; cur != NULL; cur = cur->next) {
750 xmlNodeDumpOutputInternal(ctxt, cur);
751 }
752 ctxt->format = format;
753 ctxt->level = level;
754 xmlOutputBufferWrite(buf, 2, "]>");
755}
756
764static void
765xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
767
768 if (cur == NULL) return;
769 buf = ctxt->buf;
770 if (buf == NULL) return;
771 if (ctxt->format == 2)
772 xmlOutputBufferWriteWSNonSig(ctxt, 2);
773 else
774 xmlOutputBufferWrite(buf, 1, " ");
775 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
776 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
777 xmlOutputBufferWrite(buf, 1, ":");
778 }
779 xmlOutputBufferWriteString(buf, (const char *)cur->name);
780 xmlOutputBufferWrite(buf, 2, "=\"");
781 xmlAttrSerializeContent(buf, cur);
782 xmlOutputBufferWrite(buf, 1, "\"");
783}
784
785#ifdef LIBXML_HTML_ENABLED
792static int
793htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
794 const xmlChar *oldenc = NULL;
795 const xmlChar *oldctxtenc = ctxt->encoding;
796 const xmlChar *encoding = ctxt->encoding;
797 xmlOutputBufferPtr buf = ctxt->buf;
798 int switched_encoding = 0;
799 xmlDocPtr doc;
800
802
803 doc = cur->doc;
804 if (doc != NULL) {
805 oldenc = doc->encoding;
806 if (ctxt->encoding != NULL) {
807 doc->encoding = BAD_CAST ctxt->encoding;
808 } else if (doc->encoding != NULL) {
809 encoding = doc->encoding;
810 }
811 }
812
813 if ((encoding != NULL) && (doc != NULL))
814 htmlSetMetaEncoding(doc, (const xmlChar *) encoding);
815 if ((encoding == NULL) && (doc != NULL))
816 encoding = htmlGetMetaEncoding(doc);
817 if (encoding == NULL)
818 encoding = BAD_CAST "HTML";
819 if ((encoding != NULL) && (oldctxtenc == NULL) &&
820 (buf->encoder == NULL) && (buf->conv == NULL)) {
821 if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
822 doc->encoding = oldenc;
823 return(-1);
824 }
825 switched_encoding = 1;
826 }
827 if (ctxt->options & XML_SAVE_FORMAT)
828 htmlNodeDumpFormatOutput(buf, doc, cur,
829 (const char *)encoding, 1);
830 else
831 htmlNodeDumpFormatOutput(buf, doc, cur,
832 (const char *)encoding, 0);
833 /*
834 * Restore the state of the saving context at the end of the document
835 */
836 if ((switched_encoding) && (oldctxtenc == NULL)) {
837 xmlSaveClearEncoding(ctxt);
838 }
839 if (doc != NULL)
840 doc->encoding = oldenc;
841 return(0);
842}
843#endif
844
851static void
852xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
853 int format = ctxt->format;
854 xmlNodePtr tmp, root, unformattedNode = NULL, parent;
856 xmlChar *start, *end;
858
859 if (cur == NULL) return;
860 buf = ctxt->buf;
861
862 root = cur;
863 parent = cur->parent;
864 while (1) {
865 switch (cur->type) {
868 xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
869 break;
870
871 case XML_DTD_NODE:
872 xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
873 break;
874
876 /* Always validate cur->parent when descending. */
877 if ((cur->parent == parent) && (cur->children != NULL)) {
878 parent = cur;
879 cur = cur->children;
880 continue;
881 }
882 break;
883
884 case XML_ELEMENT_DECL:
885 xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
886 break;
887
889 xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
890 break;
891
892 case XML_ENTITY_DECL:
893 xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
894 break;
895
896 case XML_ELEMENT_NODE:
897 if ((cur != root) && (ctxt->format == 1) &&
899 xmlOutputBufferWrite(buf, ctxt->indent_size *
900 (ctxt->level > ctxt->indent_nr ?
901 ctxt->indent_nr : ctxt->level),
902 ctxt->indent);
903
904 /*
905 * Some users like lxml are known to pass nodes with a corrupted
906 * tree structure. Fall back to a recursive call to handle this
907 * case.
908 */
909 if ((cur->parent != parent) && (cur->children != NULL)) {
910 xmlNodeDumpOutputInternal(ctxt, cur);
911 break;
912 }
913
914 xmlOutputBufferWrite(buf, 1, "<");
915 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
916 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
917 xmlOutputBufferWrite(buf, 1, ":");
918 }
919 xmlOutputBufferWriteString(buf, (const char *)cur->name);
920 if (cur->nsDef)
921 xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
922 for (attr = cur->properties; attr != NULL; attr = attr->next)
923 xmlAttrDumpOutput(ctxt, attr);
924
925 if (cur->children == NULL) {
926 if ((ctxt->options & XML_SAVE_NO_EMPTY) == 0) {
927 if (ctxt->format == 2)
928 xmlOutputBufferWriteWSNonSig(ctxt, 0);
929 xmlOutputBufferWrite(buf, 2, "/>");
930 } else {
931 if (ctxt->format == 2)
932 xmlOutputBufferWriteWSNonSig(ctxt, 1);
933 xmlOutputBufferWrite(buf, 3, "></");
934 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
935 xmlOutputBufferWriteString(buf,
936 (const char *)cur->ns->prefix);
937 xmlOutputBufferWrite(buf, 1, ":");
938 }
939 xmlOutputBufferWriteString(buf, (const char *)cur->name);
940 if (ctxt->format == 2)
941 xmlOutputBufferWriteWSNonSig(ctxt, 0);
942 xmlOutputBufferWrite(buf, 1, ">");
943 }
944 } else {
945 if (ctxt->format == 1) {
946 tmp = cur->children;
947 while (tmp != NULL) {
948 if ((tmp->type == XML_TEXT_NODE) ||
949 (tmp->type == XML_CDATA_SECTION_NODE) ||
950 (tmp->type == XML_ENTITY_REF_NODE)) {
951 ctxt->format = 0;
952 unformattedNode = cur;
953 break;
954 }
955 tmp = tmp->next;
956 }
957 }
958 if (ctxt->format == 2)
959 xmlOutputBufferWriteWSNonSig(ctxt, 1);
960 xmlOutputBufferWrite(buf, 1, ">");
961 if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
962 if (ctxt->level >= 0) ctxt->level++;
963 parent = cur;
964 cur = cur->children;
965 continue;
966 }
967
968 break;
969
970 case XML_TEXT_NODE:
971 if (cur->content == NULL)
972 break;
973 if (cur->name != xmlStringTextNoenc) {
974 xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
975 } else {
976 /*
977 * Disable escaping, needed for XSLT
978 */
979 xmlOutputBufferWriteString(buf, (const char *) cur->content);
980 }
981 break;
982
983 case XML_PI_NODE:
984 if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
985 xmlOutputBufferWrite(buf, ctxt->indent_size *
986 (ctxt->level > ctxt->indent_nr ?
987 ctxt->indent_nr : ctxt->level),
988 ctxt->indent);
989
990 if (cur->content != NULL) {
991 xmlOutputBufferWrite(buf, 2, "<?");
992 xmlOutputBufferWriteString(buf, (const char *)cur->name);
993 if (cur->content != NULL) {
994 if (ctxt->format == 2)
995 xmlOutputBufferWriteWSNonSig(ctxt, 0);
996 else
997 xmlOutputBufferWrite(buf, 1, " ");
998 xmlOutputBufferWriteString(buf,
999 (const char *)cur->content);
1000 }
1001 xmlOutputBufferWrite(buf, 2, "?>");
1002 } else {
1003 xmlOutputBufferWrite(buf, 2, "<?");
1004 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1005 if (ctxt->format == 2)
1006 xmlOutputBufferWriteWSNonSig(ctxt, 0);
1007 xmlOutputBufferWrite(buf, 2, "?>");
1008 }
1009 break;
1010
1011 case XML_COMMENT_NODE:
1012 if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
1013 xmlOutputBufferWrite(buf, ctxt->indent_size *
1014 (ctxt->level > ctxt->indent_nr ?
1015 ctxt->indent_nr : ctxt->level),
1016 ctxt->indent);
1017
1018 if (cur->content != NULL) {
1019 xmlOutputBufferWrite(buf, 4, "<!--");
1020 xmlOutputBufferWriteString(buf, (const char *)cur->content);
1021 xmlOutputBufferWrite(buf, 3, "-->");
1022 }
1023 break;
1024
1026 xmlOutputBufferWrite(buf, 1, "&");
1027 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1028 xmlOutputBufferWrite(buf, 1, ";");
1029 break;
1030
1032 if (cur->content == NULL || *cur->content == '\0') {
1033 xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
1034 } else {
1035 start = end = cur->content;
1036 while (*end != '\0') {
1037 if ((*end == ']') && (*(end + 1) == ']') &&
1038 (*(end + 2) == '>')) {
1039 end = end + 2;
1040 xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1041 xmlOutputBufferWrite(buf, end - start,
1042 (const char *)start);
1043 xmlOutputBufferWrite(buf, 3, "]]>");
1044 start = end;
1045 }
1046 end++;
1047 }
1048 if (start != end) {
1049 xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1050 xmlOutputBufferWriteString(buf, (const char *)start);
1051 xmlOutputBufferWrite(buf, 3, "]]>");
1052 }
1053 }
1054 break;
1055
1056 case XML_ATTRIBUTE_NODE:
1057 xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
1058 break;
1059
1060 case XML_NAMESPACE_DECL:
1061 xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
1062 break;
1063
1064 default:
1065 break;
1066 }
1067
1068 while (1) {
1069 if (cur == root)
1070 return;
1071 if ((ctxt->format == 1) &&
1072 (cur->type != XML_XINCLUDE_START) &&
1073 (cur->type != XML_XINCLUDE_END))
1074 xmlOutputBufferWrite(buf, 1, "\n");
1075 if (cur->next != NULL) {
1076 cur = cur->next;
1077 break;
1078 }
1079
1080 cur = parent;
1081 /* cur->parent was validated when descending. */
1082 parent = cur->parent;
1083
1084 if (cur->type == XML_ELEMENT_NODE) {
1085 if (ctxt->level > 0) ctxt->level--;
1086 if ((xmlIndentTreeOutput) && (ctxt->format == 1))
1087 xmlOutputBufferWrite(buf, ctxt->indent_size *
1088 (ctxt->level > ctxt->indent_nr ?
1089 ctxt->indent_nr : ctxt->level),
1090 ctxt->indent);
1091
1092 xmlOutputBufferWrite(buf, 2, "</");
1093 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1094 xmlOutputBufferWriteString(buf,
1095 (const char *)cur->ns->prefix);
1096 xmlOutputBufferWrite(buf, 1, ":");
1097 }
1098
1099 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1100 if (ctxt->format == 2)
1101 xmlOutputBufferWriteWSNonSig(ctxt, 0);
1102 xmlOutputBufferWrite(buf, 1, ">");
1103
1104 if (cur == unformattedNode) {
1105 ctxt->format = format;
1106 unformattedNode = NULL;
1107 }
1108 }
1109 }
1110 }
1111}
1112
1119static int
1120xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
1121#ifdef LIBXML_HTML_ENABLED
1122 xmlDtdPtr dtd;
1123 int is_xhtml = 0;
1124#endif
1125 const xmlChar *oldenc = cur->encoding;
1126 const xmlChar *oldctxtenc = ctxt->encoding;
1127 const xmlChar *encoding = ctxt->encoding;
1128 xmlCharEncodingOutputFunc oldescape = ctxt->escape;
1129 xmlCharEncodingOutputFunc oldescapeAttr = ctxt->escapeAttr;
1130 xmlOutputBufferPtr buf = ctxt->buf;
1131 xmlCharEncoding enc;
1132 int switched_encoding = 0;
1133
1134 xmlInitParser();
1135
1136 if ((cur->type != XML_HTML_DOCUMENT_NODE) &&
1137 (cur->type != XML_DOCUMENT_NODE))
1138 return(-1);
1139
1140 if (ctxt->encoding != NULL) {
1141 cur->encoding = BAD_CAST ctxt->encoding;
1142 } else if (cur->encoding != NULL) {
1143 encoding = cur->encoding;
1144 }
1145
1146 if (((cur->type == XML_HTML_DOCUMENT_NODE) &&
1147 ((ctxt->options & XML_SAVE_AS_XML) == 0) &&
1148 ((ctxt->options & XML_SAVE_XHTML) == 0)) ||
1149 (ctxt->options & XML_SAVE_AS_HTML)) {
1150#ifdef LIBXML_HTML_ENABLED
1151 if (encoding != NULL)
1152 htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
1153 if (encoding == NULL)
1154 encoding = htmlGetMetaEncoding(cur);
1155 if (encoding == NULL)
1156 encoding = BAD_CAST "HTML";
1157 if ((encoding != NULL) && (oldctxtenc == NULL) &&
1158 (buf->encoder == NULL) && (buf->conv == NULL)) {
1159 if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
1160 cur->encoding = oldenc;
1161 return(-1);
1162 }
1163 }
1164 if (ctxt->options & XML_SAVE_FORMAT)
1165 htmlDocContentDumpFormatOutput(buf, cur,
1166 (const char *)encoding, 1);
1167 else
1168 htmlDocContentDumpFormatOutput(buf, cur,
1169 (const char *)encoding, 0);
1170 if (ctxt->encoding != NULL)
1171 cur->encoding = oldenc;
1172 return(0);
1173#else
1174 return(-1);
1175#endif
1176 } else if ((cur->type == XML_DOCUMENT_NODE) ||
1177 (ctxt->options & XML_SAVE_AS_XML) ||
1178 (ctxt->options & XML_SAVE_XHTML)) {
1179 enc = xmlParseCharEncoding((const char*) encoding);
1180 if ((encoding != NULL) && (oldctxtenc == NULL) &&
1181 (buf->encoder == NULL) && (buf->conv == NULL) &&
1182 ((ctxt->options & XML_SAVE_NO_DECL) == 0)) {
1183 if ((enc != XML_CHAR_ENCODING_UTF8) &&
1184 (enc != XML_CHAR_ENCODING_NONE) &&
1185 (enc != XML_CHAR_ENCODING_ASCII)) {
1186 /*
1187 * we need to switch to this encoding but just for this
1188 * document since we output the XMLDecl the conversion
1189 * must be done to not generate not well formed documents.
1190 */
1191 if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
1192 cur->encoding = oldenc;
1193 return(-1);
1194 }
1195 switched_encoding = 1;
1196 }
1197 if (ctxt->escape == xmlEscapeEntities)
1198 ctxt->escape = NULL;
1199 if (ctxt->escapeAttr == xmlEscapeEntities)
1200 ctxt->escapeAttr = NULL;
1201 }
1202
1203
1204 /*
1205 * Save the XML declaration
1206 */
1207 if ((ctxt->options & XML_SAVE_NO_DECL) == 0) {
1208 xmlOutputBufferWrite(buf, 14, "<?xml version=");
1209 if (cur->version != NULL)
1210 xmlBufWriteQuotedString(buf->buffer, cur->version);
1211 else
1212 xmlOutputBufferWrite(buf, 5, "\"1.0\"");
1213 if (encoding != NULL) {
1214 xmlOutputBufferWrite(buf, 10, " encoding=");
1216 }
1217 switch (cur->standalone) {
1218 case 0:
1219 xmlOutputBufferWrite(buf, 16, " standalone=\"no\"");
1220 break;
1221 case 1:
1222 xmlOutputBufferWrite(buf, 17, " standalone=\"yes\"");
1223 break;
1224 }
1225 xmlOutputBufferWrite(buf, 3, "?>\n");
1226 }
1227
1228#ifdef LIBXML_HTML_ENABLED
1229 if (ctxt->options & XML_SAVE_XHTML)
1230 is_xhtml = 1;
1231 if ((ctxt->options & XML_SAVE_NO_XHTML) == 0) {
1232 dtd = xmlGetIntSubset(cur);
1233 if (dtd != NULL) {
1234 is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
1235 if (is_xhtml < 0) is_xhtml = 0;
1236 }
1237 }
1238#endif
1239 if (cur->children != NULL) {
1240 xmlNodePtr child = cur->children;
1241
1242 while (child != NULL) {
1243 ctxt->level = 0;
1244#ifdef LIBXML_HTML_ENABLED
1245 if (is_xhtml)
1246 xhtmlNodeDumpOutput(ctxt, child);
1247 else
1248#endif
1249 xmlNodeDumpOutputInternal(ctxt, child);
1250 if ((child->type != XML_XINCLUDE_START) &&
1251 (child->type != XML_XINCLUDE_END))
1252 xmlOutputBufferWrite(buf, 1, "\n");
1253 child = child->next;
1254 }
1255 }
1256 }
1257
1258 /*
1259 * Restore the state of the saving context at the end of the document
1260 */
1261 if ((switched_encoding) && (oldctxtenc == NULL)) {
1262 xmlSaveClearEncoding(ctxt);
1263 ctxt->escape = oldescape;
1264 ctxt->escapeAttr = oldescapeAttr;
1265 }
1266 cur->encoding = oldenc;
1267 return(0);
1268}
1269
1270#ifdef LIBXML_HTML_ENABLED
1271/************************************************************************
1272 * *
1273 * Functions specific to XHTML serialization *
1274 * *
1275 ************************************************************************/
1276
1285static int
1286xhtmlIsEmpty(xmlNodePtr node) {
1287 if (node == NULL)
1288 return(-1);
1289 if (node->type != XML_ELEMENT_NODE)
1290 return(0);
1291 if ((node->ns != NULL) && (!xmlStrEqual(node->ns->href, XHTML_NS_NAME)))
1292 return(0);
1293 if (node->children != NULL)
1294 return(0);
1295 switch (node->name[0]) {
1296 case 'a':
1297 if (xmlStrEqual(node->name, BAD_CAST "area"))
1298 return(1);
1299 return(0);
1300 case 'b':
1301 if (xmlStrEqual(node->name, BAD_CAST "br"))
1302 return(1);
1303 if (xmlStrEqual(node->name, BAD_CAST "base"))
1304 return(1);
1305 if (xmlStrEqual(node->name, BAD_CAST "basefont"))
1306 return(1);
1307 return(0);
1308 case 'c':
1309 if (xmlStrEqual(node->name, BAD_CAST "col"))
1310 return(1);
1311 return(0);
1312 case 'f':
1313 if (xmlStrEqual(node->name, BAD_CAST "frame"))
1314 return(1);
1315 return(0);
1316 case 'h':
1317 if (xmlStrEqual(node->name, BAD_CAST "hr"))
1318 return(1);
1319 return(0);
1320 case 'i':
1321 if (xmlStrEqual(node->name, BAD_CAST "img"))
1322 return(1);
1323 if (xmlStrEqual(node->name, BAD_CAST "input"))
1324 return(1);
1325 if (xmlStrEqual(node->name, BAD_CAST "isindex"))
1326 return(1);
1327 return(0);
1328 case 'l':
1329 if (xmlStrEqual(node->name, BAD_CAST "link"))
1330 return(1);
1331 return(0);
1332 case 'm':
1333 if (xmlStrEqual(node->name, BAD_CAST "meta"))
1334 return(1);
1335 return(0);
1336 case 'p':
1337 if (xmlStrEqual(node->name, BAD_CAST "param"))
1338 return(1);
1339 return(0);
1340 }
1341 return(0);
1342}
1343
1350static void
1351xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
1352 xmlAttrPtr xml_lang = NULL;
1355 xmlAttrPtr id = NULL;
1358
1359 if (cur == NULL) return;
1360 buf = ctxt->buf;
1361 parent = cur->parent;
1362 while (cur != NULL) {
1363 if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "id")))
1364 id = cur;
1365 else
1366 if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "name")))
1367 name = cur;
1368 else
1369 if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")))
1370 lang = cur;
1371 else
1372 if ((cur->ns != NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")) &&
1373 (xmlStrEqual(cur->ns->prefix, BAD_CAST "xml")))
1374 xml_lang = cur;
1375 else if ((cur->ns == NULL) &&
1376 ((cur->children == NULL) ||
1377 (cur->children->content == NULL) ||
1378 (cur->children->content[0] == 0)) &&
1379 (htmlIsBooleanAttr(cur->name))) {
1380 if (cur->children != NULL)
1381 xmlFreeNode(cur->children);
1382 cur->children = xmlNewDocText(cur->doc, cur->name);
1383 if (cur->children != NULL)
1384 cur->children->parent = (xmlNodePtr) cur;
1385 }
1386 xmlAttrDumpOutput(ctxt, cur);
1387 cur = cur->next;
1388 }
1389 /*
1390 * C.8
1391 */
1392 if ((name != NULL) && (id == NULL)) {
1393 if ((parent != NULL) && (parent->name != NULL) &&
1394 ((xmlStrEqual(parent->name, BAD_CAST "a")) ||
1395 (xmlStrEqual(parent->name, BAD_CAST "p")) ||
1396 (xmlStrEqual(parent->name, BAD_CAST "div")) ||
1397 (xmlStrEqual(parent->name, BAD_CAST "img")) ||
1398 (xmlStrEqual(parent->name, BAD_CAST "map")) ||
1399 (xmlStrEqual(parent->name, BAD_CAST "applet")) ||
1400 (xmlStrEqual(parent->name, BAD_CAST "form")) ||
1401 (xmlStrEqual(parent->name, BAD_CAST "frame")) ||
1402 (xmlStrEqual(parent->name, BAD_CAST "iframe")))) {
1403 xmlOutputBufferWrite(buf, 5, " id=\"");
1404 xmlAttrSerializeContent(buf, name);
1405 xmlOutputBufferWrite(buf, 1, "\"");
1406 }
1407 }
1408 /*
1409 * C.7.
1410 */
1411 if ((lang != NULL) && (xml_lang == NULL)) {
1412 xmlOutputBufferWrite(buf, 11, " xml:lang=\"");
1413 xmlAttrSerializeContent(buf, lang);
1414 xmlOutputBufferWrite(buf, 1, "\"");
1415 } else
1416 if ((xml_lang != NULL) && (lang == NULL)) {
1417 xmlOutputBufferWrite(buf, 7, " lang=\"");
1418 xmlAttrSerializeContent(buf, xml_lang);
1419 xmlOutputBufferWrite(buf, 1, "\"");
1420 }
1421}
1422
1434static void
1435xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
1436 int format = ctxt->format, addmeta;
1437 xmlNodePtr tmp, root, unformattedNode = NULL;
1438 xmlChar *start, *end;
1439 xmlOutputBufferPtr buf = ctxt->buf;
1440
1441 if (cur == NULL) return;
1442
1443 root = cur;
1444 while (1) {
1445 switch (cur->type) {
1446 case XML_DOCUMENT_NODE:
1448 xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
1449 break;
1450
1451 case XML_NAMESPACE_DECL:
1452 xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
1453 break;
1454
1455 case XML_DTD_NODE:
1456 xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
1457 break;
1458
1460 if (cur->children) {
1461 cur = cur->children;
1462 continue;
1463 }
1464 break;
1465
1466 case XML_ELEMENT_DECL:
1467 xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
1468 break;
1469
1470 case XML_ATTRIBUTE_DECL:
1471 xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
1472 break;
1473
1474 case XML_ENTITY_DECL:
1475 xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
1476 break;
1477
1478 case XML_ELEMENT_NODE:
1479 addmeta = 0;
1480
1481 if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
1482 xmlOutputBufferWrite(buf, ctxt->indent_size *
1483 (ctxt->level > ctxt->indent_nr ?
1484 ctxt->indent_nr : ctxt->level),
1485 ctxt->indent);
1486
1487 xmlOutputBufferWrite(buf, 1, "<");
1488 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1489 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
1490 xmlOutputBufferWrite(buf, 1, ":");
1491 }
1492
1493 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1494 if (cur->nsDef)
1495 xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
1496 if ((xmlStrEqual(cur->name, BAD_CAST "html") &&
1497 (cur->ns == NULL) && (cur->nsDef == NULL))) {
1498 /*
1499 * 3.1.1. Strictly Conforming Documents A.3.1.1 3/
1500 */
1501 xmlOutputBufferWriteString(buf,
1502 " xmlns=\"http://www.w3.org/1999/xhtml\"");
1503 }
1504 if (cur->properties != NULL)
1505 xhtmlAttrListDumpOutput(ctxt, cur->properties);
1506
1507 if ((cur->parent != NULL) &&
1508 (cur->parent->parent == (xmlNodePtr) cur->doc) &&
1509 xmlStrEqual(cur->name, BAD_CAST"head") &&
1510 xmlStrEqual(cur->parent->name, BAD_CAST"html")) {
1511
1512 tmp = cur->children;
1513 while (tmp != NULL) {
1514 if (xmlStrEqual(tmp->name, BAD_CAST"meta")) {
1515 xmlChar *httpequiv;
1516
1517 httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv");
1518 if (httpequiv != NULL) {
1519 if (xmlStrcasecmp(httpequiv,
1520 BAD_CAST"Content-Type") == 0) {
1521 xmlFree(httpequiv);
1522 break;
1523 }
1524 xmlFree(httpequiv);
1525 }
1526 }
1527 tmp = tmp->next;
1528 }
1529 if (tmp == NULL)
1530 addmeta = 1;
1531 }
1532
1533 if (cur->children == NULL) {
1534 if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) &&
1535 ((xhtmlIsEmpty(cur) == 1) && (addmeta == 0))) {
1536 /*
1537 * C.2. Empty Elements
1538 */
1539 xmlOutputBufferWrite(buf, 3, " />");
1540 } else {
1541 if (addmeta == 1) {
1542 xmlOutputBufferWrite(buf, 1, ">");
1543 if (ctxt->format == 1) {
1544 xmlOutputBufferWrite(buf, 1, "\n");
1546 xmlOutputBufferWrite(buf, ctxt->indent_size *
1547 (ctxt->level + 1 > ctxt->indent_nr ?
1548 ctxt->indent_nr : ctxt->level + 1),
1549 ctxt->indent);
1550 }
1551 xmlOutputBufferWriteString(buf,
1552 "<meta http-equiv=\"Content-Type\" "
1553 "content=\"text/html; charset=");
1554 if (ctxt->encoding) {
1555 xmlOutputBufferWriteString(buf,
1556 (const char *)ctxt->encoding);
1557 } else {
1558 xmlOutputBufferWrite(buf, 5, "UTF-8");
1559 }
1560 xmlOutputBufferWrite(buf, 4, "\" />");
1561 if (ctxt->format == 1)
1562 xmlOutputBufferWrite(buf, 1, "\n");
1563 } else {
1564 xmlOutputBufferWrite(buf, 1, ">");
1565 }
1566 /*
1567 * C.3. Element Minimization and Empty Element Content
1568 */
1569 xmlOutputBufferWrite(buf, 2, "</");
1570 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1571 xmlOutputBufferWriteString(buf,
1572 (const char *)cur->ns->prefix);
1573 xmlOutputBufferWrite(buf, 1, ":");
1574 }
1575 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1576 xmlOutputBufferWrite(buf, 1, ">");
1577 }
1578 } else {
1579 xmlOutputBufferWrite(buf, 1, ">");
1580 if (addmeta == 1) {
1581 if (ctxt->format == 1) {
1582 xmlOutputBufferWrite(buf, 1, "\n");
1584 xmlOutputBufferWrite(buf, ctxt->indent_size *
1585 (ctxt->level + 1 > ctxt->indent_nr ?
1586 ctxt->indent_nr : ctxt->level + 1),
1587 ctxt->indent);
1588 }
1589 xmlOutputBufferWriteString(buf,
1590 "<meta http-equiv=\"Content-Type\" "
1591 "content=\"text/html; charset=");
1592 if (ctxt->encoding) {
1593 xmlOutputBufferWriteString(buf,
1594 (const char *)ctxt->encoding);
1595 } else {
1596 xmlOutputBufferWrite(buf, 5, "UTF-8");
1597 }
1598 xmlOutputBufferWrite(buf, 4, "\" />");
1599 }
1600
1601 if (ctxt->format == 1) {
1602 tmp = cur->children;
1603 while (tmp != NULL) {
1604 if ((tmp->type == XML_TEXT_NODE) ||
1605 (tmp->type == XML_ENTITY_REF_NODE)) {
1606 unformattedNode = cur;
1607 ctxt->format = 0;
1608 break;
1609 }
1610 tmp = tmp->next;
1611 }
1612 }
1613
1614 if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
1615 if (ctxt->level >= 0) ctxt->level++;
1616 cur = cur->children;
1617 continue;
1618 }
1619
1620 break;
1621
1622 case XML_TEXT_NODE:
1623 if (cur->content == NULL)
1624 break;
1625 if ((cur->name == xmlStringText) ||
1626 (cur->name != xmlStringTextNoenc)) {
1627 xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
1628 } else {
1629 /*
1630 * Disable escaping, needed for XSLT
1631 */
1632 xmlOutputBufferWriteString(buf, (const char *) cur->content);
1633 }
1634 break;
1635
1636 case XML_PI_NODE:
1637 if (cur->content != NULL) {
1638 xmlOutputBufferWrite(buf, 2, "<?");
1639 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1640 if (cur->content != NULL) {
1641 xmlOutputBufferWrite(buf, 1, " ");
1642 xmlOutputBufferWriteString(buf,
1643 (const char *)cur->content);
1644 }
1645 xmlOutputBufferWrite(buf, 2, "?>");
1646 } else {
1647 xmlOutputBufferWrite(buf, 2, "<?");
1648 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1649 xmlOutputBufferWrite(buf, 2, "?>");
1650 }
1651 break;
1652
1653 case XML_COMMENT_NODE:
1654 if (cur->content != NULL) {
1655 xmlOutputBufferWrite(buf, 4, "<!--");
1656 xmlOutputBufferWriteString(buf, (const char *)cur->content);
1657 xmlOutputBufferWrite(buf, 3, "-->");
1658 }
1659 break;
1660
1662 xmlOutputBufferWrite(buf, 1, "&");
1663 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1664 xmlOutputBufferWrite(buf, 1, ";");
1665 break;
1666
1668 if (cur->content == NULL || *cur->content == '\0') {
1669 xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
1670 } else {
1671 start = end = cur->content;
1672 while (*end != '\0') {
1673 if (*end == ']' && *(end + 1) == ']' &&
1674 *(end + 2) == '>') {
1675 end = end + 2;
1676 xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1677 xmlOutputBufferWrite(buf, end - start,
1678 (const char *)start);
1679 xmlOutputBufferWrite(buf, 3, "]]>");
1680 start = end;
1681 }
1682 end++;
1683 }
1684 if (start != end) {
1685 xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1686 xmlOutputBufferWriteString(buf, (const char *)start);
1687 xmlOutputBufferWrite(buf, 3, "]]>");
1688 }
1689 }
1690 break;
1691
1692 case XML_ATTRIBUTE_NODE:
1693 xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
1694 break;
1695
1696 default:
1697 break;
1698 }
1699
1700 while (1) {
1701 if (cur == root)
1702 return;
1703 if (ctxt->format == 1)
1704 xmlOutputBufferWrite(buf, 1, "\n");
1705 if (cur->next != NULL) {
1706 cur = cur->next;
1707 break;
1708 }
1709
1710 /*
1711 * The parent should never be NULL here but we want to handle
1712 * corrupted documents gracefully.
1713 */
1714 if (cur->parent == NULL)
1715 return;
1716 cur = cur->parent;
1717
1718 if (cur->type == XML_ELEMENT_NODE) {
1719 if (ctxt->level > 0) ctxt->level--;
1720 if ((xmlIndentTreeOutput) && (ctxt->format == 1))
1721 xmlOutputBufferWrite(buf, ctxt->indent_size *
1722 (ctxt->level > ctxt->indent_nr ?
1723 ctxt->indent_nr : ctxt->level),
1724 ctxt->indent);
1725
1726 xmlOutputBufferWrite(buf, 2, "</");
1727 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1728 xmlOutputBufferWriteString(buf,
1729 (const char *)cur->ns->prefix);
1730 xmlOutputBufferWrite(buf, 1, ":");
1731 }
1732
1733 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1734 xmlOutputBufferWrite(buf, 1, ">");
1735
1736 if (cur == unformattedNode) {
1737 ctxt->format = format;
1738 unformattedNode = NULL;
1739 }
1740 }
1741 }
1742 }
1743}
1744#endif
1745
1746/************************************************************************
1747 * *
1748 * Public entry points *
1749 * *
1750 ************************************************************************/
1751
1763xmlSaveCtxtPtr
1764xmlSaveToFd(int fd, const char *encoding, int options)
1765{
1766 xmlSaveCtxtPtr ret;
1767
1768 ret = xmlNewSaveCtxt(encoding, options);
1769 if (ret == NULL) return(NULL);
1770 ret->buf = xmlOutputBufferCreateFd(fd, ret->handler);
1771 if (ret->buf == NULL) {
1772 xmlCharEncCloseFunc(ret->handler);
1773 xmlFreeSaveCtxt(ret);
1774 return(NULL);
1775 }
1776 return(ret);
1777}
1778
1791xmlSaveCtxtPtr
1792xmlSaveToFilename(const char *filename, const char *encoding, int options)
1793{
1794 xmlSaveCtxtPtr ret;
1795 int compression = 0; /* TODO handle compression option */
1796
1797 ret = xmlNewSaveCtxt(encoding, options);
1798 if (ret == NULL) return(NULL);
1799 ret->buf = xmlOutputBufferCreateFilename(filename, ret->handler,
1800 compression);
1801 if (ret->buf == NULL) {
1802 xmlCharEncCloseFunc(ret->handler);
1803 xmlFreeSaveCtxt(ret);
1804 return(NULL);
1805 }
1806 return(ret);
1807}
1808
1821xmlSaveCtxtPtr
1822xmlSaveToBuffer(xmlBufferPtr buffer, const char *encoding, int options)
1823{
1824 xmlSaveCtxtPtr ret;
1825
1826 ret = xmlNewSaveCtxt(encoding, options);
1827 if (ret == NULL) return(NULL);
1828 ret->buf = xmlOutputBufferCreateBuffer(buffer, ret->handler);
1829 if (ret->buf == NULL) {
1830 xmlCharEncCloseFunc(ret->handler);
1831 xmlFreeSaveCtxt(ret);
1832 return(NULL);
1833 }
1834 return(ret);
1835}
1836
1850xmlSaveCtxtPtr
1851xmlSaveToIO(xmlOutputWriteCallback iowrite,
1852 xmlOutputCloseCallback ioclose,
1853 void *ioctx, const char *encoding, int options)
1854{
1855 xmlSaveCtxtPtr ret;
1856
1857 ret = xmlNewSaveCtxt(encoding, options);
1858 if (ret == NULL) return(NULL);
1859 ret->buf = xmlOutputBufferCreateIO(iowrite, ioclose, ioctx, ret->handler);
1860 if (ret->buf == NULL) {
1861 xmlCharEncCloseFunc(ret->handler);
1862 xmlFreeSaveCtxt(ret);
1863 return(NULL);
1864 }
1865 return(ret);
1866}
1867
1879long
1880xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc)
1881{
1882 long ret = 0;
1883
1884 if ((ctxt == NULL) || (doc == NULL)) return(-1);
1885 if (xmlDocContentDumpOutput(ctxt, doc) < 0)
1886 return(-1);
1887 return(ret);
1888}
1889
1901long
1902xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr cur)
1903{
1904 long ret = 0;
1905
1906 if ((ctxt == NULL) || (cur == NULL)) return(-1);
1907#ifdef LIBXML_HTML_ENABLED
1908 if (ctxt->options & XML_SAVE_XHTML) {
1909 xhtmlNodeDumpOutput(ctxt, cur);
1910 return(ret);
1911 }
1912 if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
1913 (cur->doc->type == XML_HTML_DOCUMENT_NODE) &&
1914 ((ctxt->options & XML_SAVE_AS_XML) == 0)) ||
1915 (ctxt->options & XML_SAVE_AS_HTML)) {
1916 htmlNodeDumpOutputInternal(ctxt, cur);
1917 return(ret);
1918 }
1919#endif
1920 xmlNodeDumpOutputInternal(ctxt, cur);
1921 return(ret);
1922}
1923
1933int
1934xmlSaveFlush(xmlSaveCtxtPtr ctxt)
1935{
1936 if (ctxt == NULL) return(-1);
1937 if (ctxt->buf == NULL) return(-1);
1938 return(xmlOutputBufferFlush(ctxt->buf));
1939}
1940
1950int
1951xmlSaveClose(xmlSaveCtxtPtr ctxt)
1952{
1953 int ret;
1954
1955 if (ctxt == NULL) return(-1);
1956 ret = xmlSaveFlush(ctxt);
1957 xmlFreeSaveCtxt(ctxt);
1958 return(ret);
1959}
1960
1970int
1971xmlSaveSetEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape)
1972{
1973 if (ctxt == NULL) return(-1);
1974 ctxt->escape = escape;
1975 return(0);
1976}
1977
1987int
1988xmlSaveSetAttrEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape)
1989{
1990 if (ctxt == NULL) return(-1);
1991 ctxt->escapeAttr = escape;
1992 return(0);
1993}
1994
1995/************************************************************************
1996 * *
1997 * Public entry points based on buffers *
1998 * *
1999 ************************************************************************/
2000
2010void
2011xmlBufAttrSerializeTxtContent(xmlBufPtr buf, xmlDocPtr doc,
2012 xmlAttrPtr attr, const xmlChar * string)
2013{
2014 xmlChar *base, *cur;
2015
2016 if (string == NULL)
2017 return;
2018 base = cur = (xmlChar *) string;
2019 while (*cur != 0) {
2020 if (*cur == '\n') {
2021 if (base != cur)
2022 xmlBufAdd(buf, base, cur - base);
2023 xmlBufAdd(buf, BAD_CAST "&#10;", 5);
2024 cur++;
2025 base = cur;
2026 } else if (*cur == '\r') {
2027 if (base != cur)
2028 xmlBufAdd(buf, base, cur - base);
2029 xmlBufAdd(buf, BAD_CAST "&#13;", 5);
2030 cur++;
2031 base = cur;
2032 } else if (*cur == '\t') {
2033 if (base != cur)
2034 xmlBufAdd(buf, base, cur - base);
2035 xmlBufAdd(buf, BAD_CAST "&#9;", 4);
2036 cur++;
2037 base = cur;
2038 } else if (*cur == '"') {
2039 if (base != cur)
2040 xmlBufAdd(buf, base, cur - base);
2041 xmlBufAdd(buf, BAD_CAST "&quot;", 6);
2042 cur++;
2043 base = cur;
2044 } else if (*cur == '<') {
2045 if (base != cur)
2046 xmlBufAdd(buf, base, cur - base);
2047 xmlBufAdd(buf, BAD_CAST "&lt;", 4);
2048 cur++;
2049 base = cur;
2050 } else if (*cur == '>') {
2051 if (base != cur)
2052 xmlBufAdd(buf, base, cur - base);
2053 xmlBufAdd(buf, BAD_CAST "&gt;", 4);
2054 cur++;
2055 base = cur;
2056 } else if (*cur == '&') {
2057 if (base != cur)
2058 xmlBufAdd(buf, base, cur - base);
2059 xmlBufAdd(buf, BAD_CAST "&amp;", 5);
2060 cur++;
2061 base = cur;
2062 } else if ((*cur >= 0x80) && (cur[1] != 0) &&
2063 ((doc == NULL) || (doc->encoding == NULL))) {
2064 /*
2065 * We assume we have UTF-8 content.
2066 */
2067 unsigned char tmp[12];
2068 int val = 0, l = 1;
2069
2070 if (base != cur)
2071 xmlBufAdd(buf, base, cur - base);
2072 if (*cur < 0xC0) {
2073 xmlSaveErr(XML_SAVE_NOT_UTF8, (xmlNodePtr) attr, NULL);
2074 xmlSerializeHexCharRef(tmp, *cur);
2075 xmlBufAdd(buf, (xmlChar *) tmp, -1);
2076 cur++;
2077 base = cur;
2078 continue;
2079 } else if (*cur < 0xE0) {
2080 val = (cur[0]) & 0x1F;
2081 val <<= 6;
2082 val |= (cur[1]) & 0x3F;
2083 l = 2;
2084 } else if ((*cur < 0xF0) && (cur [2] != 0)) {
2085 val = (cur[0]) & 0x0F;
2086 val <<= 6;
2087 val |= (cur[1]) & 0x3F;
2088 val <<= 6;
2089 val |= (cur[2]) & 0x3F;
2090 l = 3;
2091 } else if ((*cur < 0xF8) && (cur [2] != 0) && (cur[3] != 0)) {
2092 val = (cur[0]) & 0x07;
2093 val <<= 6;
2094 val |= (cur[1]) & 0x3F;
2095 val <<= 6;
2096 val |= (cur[2]) & 0x3F;
2097 val <<= 6;
2098 val |= (cur[3]) & 0x3F;
2099 l = 4;
2100 }
2101 if ((l == 1) || (!IS_CHAR(val))) {
2102 xmlSaveErr(XML_SAVE_CHAR_INVALID, (xmlNodePtr) attr, NULL);
2103 xmlSerializeHexCharRef(tmp, *cur);
2104 xmlBufAdd(buf, (xmlChar *) tmp, -1);
2105 cur++;
2106 base = cur;
2107 continue;
2108 }
2109 /*
2110 * We could do multiple things here. Just save
2111 * as a char ref
2112 */
2113 xmlSerializeHexCharRef(tmp, val);
2114 xmlBufAdd(buf, (xmlChar *) tmp, -1);
2115 cur += l;
2116 base = cur;
2117 } else {
2118 cur++;
2119 }
2120 }
2121 if (base != cur)
2122 xmlBufAdd(buf, base, cur - base);
2123}
2124
2134void
2135xmlAttrSerializeTxtContent(xmlBufferPtr buf, xmlDocPtr doc,
2136 xmlAttrPtr attr, const xmlChar * string)
2137{
2139
2140 if ((buf == NULL) || (string == NULL))
2141 return;
2143 if (buffer == NULL)
2144 return;
2145 xmlBufAttrSerializeTxtContent(buffer, doc, attr, string);
2147}
2148
2165int
2166xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2167 int format)
2168{
2170 size_t ret;
2171
2172 if ((buf == NULL) || (cur == NULL))
2173 return(-1);
2175 if (buffer == NULL)
2176 return(-1);
2177 ret = xmlBufNodeDump(buffer, doc, cur, level, format);
2179 if (ret > INT_MAX)
2180 return(-1);
2181 return((int) ret);
2182}
2183
2200size_t
2201xmlBufNodeDump(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2202 int format)
2203{
2204 size_t use;
2205 int ret;
2206 xmlOutputBufferPtr outbuf;
2207 int oldalloc;
2208
2209 xmlInitParser();
2210
2211 if (cur == NULL) {
2212#ifdef DEBUG_TREE
2214 "xmlNodeDump : node == NULL\n");
2215#endif
2216 return (-1);
2217 }
2218 if (buf == NULL) {
2219#ifdef DEBUG_TREE
2221 "xmlNodeDump : buf == NULL\n");
2222#endif
2223 return (-1);
2224 }
2225 outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
2226 if (outbuf == NULL) {
2227 xmlSaveErrMemory("creating buffer");
2228 return (-1);
2229 }
2230 memset(outbuf, 0, (size_t) sizeof(xmlOutputBuffer));
2231 outbuf->buffer = buf;
2232 outbuf->encoder = NULL;
2233 outbuf->writecallback = NULL;
2234 outbuf->closecallback = NULL;
2235 outbuf->context = NULL;
2236 outbuf->written = 0;
2237
2238 use = xmlBufUse(buf);
2239 oldalloc = xmlBufGetAllocationScheme(buf);
2241 xmlNodeDumpOutput(outbuf, doc, cur, level, format, NULL);
2242 xmlBufSetAllocationScheme(buf, oldalloc);
2243 xmlFree(outbuf);
2244 ret = xmlBufUse(buf) - use;
2245 return (ret);
2246}
2247
2256void
2257xmlElemDump(FILE * f, xmlDocPtr doc, xmlNodePtr cur)
2258{
2259 xmlOutputBufferPtr outbuf;
2260
2261 xmlInitParser();
2262
2263 if (cur == NULL) {
2264#ifdef DEBUG_TREE
2266 "xmlElemDump : cur == NULL\n");
2267#endif
2268 return;
2269 }
2270#ifdef DEBUG_TREE
2271 if (doc == NULL) {
2273 "xmlElemDump : doc == NULL\n");
2274 }
2275#endif
2276
2277 outbuf = xmlOutputBufferCreateFile(f, NULL);
2278 if (outbuf == NULL)
2279 return;
2280 if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
2281#ifdef LIBXML_HTML_ENABLED
2282 htmlNodeDumpOutput(outbuf, doc, cur, NULL);
2283#else
2284 xmlSaveErr(XML_ERR_INTERNAL_ERROR, cur, "HTML support not compiled in\n");
2285#endif /* LIBXML_HTML_ENABLED */
2286 } else
2287 xmlNodeDumpOutput(outbuf, doc, cur, 0, 1, NULL);
2288 xmlOutputBufferClose(outbuf);
2289}
2290
2291/************************************************************************
2292 * *
2293 * Saving functions front-ends *
2294 * *
2295 ************************************************************************/
2296
2310void
2311xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
2312 int level, int format, const char *encoding)
2313{
2314 xmlSaveCtxt ctxt;
2315#ifdef LIBXML_HTML_ENABLED
2316 xmlDtdPtr dtd;
2317 int is_xhtml = 0;
2318#endif
2319
2320 xmlInitParser();
2321
2322 if ((buf == NULL) || (cur == NULL)) return;
2323
2324 if (encoding == NULL)
2325 encoding = "UTF-8";
2326
2327 memset(&ctxt, 0, sizeof(ctxt));
2328 ctxt.buf = buf;
2329 ctxt.level = level;
2330 ctxt.format = format ? 1 : 0;
2331 ctxt.encoding = (const xmlChar *) encoding;
2332 xmlSaveCtxtInit(&ctxt);
2333 ctxt.options |= XML_SAVE_AS_XML;
2334
2335#ifdef LIBXML_HTML_ENABLED
2336 dtd = xmlGetIntSubset(doc);
2337 if (dtd != NULL) {
2338 is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
2339 if (is_xhtml < 0)
2340 is_xhtml = 0;
2341 }
2342
2343 if (is_xhtml)
2344 xhtmlNodeDumpOutput(&ctxt, cur);
2345 else
2346#endif
2347 xmlNodeDumpOutputInternal(&ctxt, cur);
2348}
2349
2365void
2366xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
2367 int * doc_txt_len, const char * txt_encoding,
2368 int format) {
2369 xmlSaveCtxt ctxt;
2370 int dummy = 0;
2371 xmlOutputBufferPtr out_buff = NULL;
2372 xmlCharEncodingHandlerPtr conv_hdlr = NULL;
2373
2374 if (doc_txt_len == NULL) {
2375 doc_txt_len = &dummy; /* Continue, caller just won't get length */
2376 }
2377
2378 if (doc_txt_ptr == NULL) {
2379 *doc_txt_len = 0;
2380 return;
2381 }
2382
2383 *doc_txt_ptr = NULL;
2384 *doc_txt_len = 0;
2385
2386 if (out_doc == NULL) {
2387 /* No document, no output */
2388 return;
2389 }
2390
2391 /*
2392 * Validate the encoding value, if provided.
2393 * This logic is copied from xmlSaveFileEnc.
2394 */
2395
2396 if (txt_encoding == NULL)
2397 txt_encoding = (const char *) out_doc->encoding;
2398 if (txt_encoding != NULL) {
2399 conv_hdlr = xmlFindCharEncodingHandler(txt_encoding);
2400 if ( conv_hdlr == NULL ) {
2401 xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, (xmlNodePtr) out_doc,
2402 txt_encoding);
2403 return;
2404 }
2405 }
2406
2407 if ((out_buff = xmlAllocOutputBuffer(conv_hdlr)) == NULL ) {
2408 xmlSaveErrMemory("creating buffer");
2409 return;
2410 }
2411
2412 memset(&ctxt, 0, sizeof(ctxt));
2413 ctxt.buf = out_buff;
2414 ctxt.level = 0;
2415 ctxt.format = format ? 1 : 0;
2416 ctxt.encoding = (const xmlChar *) txt_encoding;
2417 xmlSaveCtxtInit(&ctxt);
2418 ctxt.options |= XML_SAVE_AS_XML;
2419 xmlDocContentDumpOutput(&ctxt, out_doc);
2420 xmlOutputBufferFlush(out_buff);
2421 if (out_buff->conv != NULL) {
2422 *doc_txt_len = xmlBufUse(out_buff->conv);
2423 *doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->conv), *doc_txt_len);
2424 } else {
2425 *doc_txt_len = xmlBufUse(out_buff->buffer);
2426 *doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->buffer),*doc_txt_len);
2427 }
2428 (void)xmlOutputBufferClose(out_buff);
2429
2430 if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) {
2431 *doc_txt_len = 0;
2432 xmlSaveErrMemory("creating output");
2433 }
2434
2435 return;
2436}
2437
2449void
2450xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
2451 xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, 0);
2452}
2453
2467void
2468xmlDocDumpFormatMemory(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
2469 xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, format);
2470}
2471
2484void
2485xmlDocDumpMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
2486 int * doc_txt_len, const char * txt_encoding) {
2487 xmlDocDumpFormatMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len,
2488 txt_encoding, 0);
2489}
2490
2503int
2504xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) {
2505 xmlSaveCtxt ctxt;
2507 const char * encoding;
2509 int ret;
2510
2511 if (cur == NULL) {
2512#ifdef DEBUG_TREE
2514 "xmlDocDump : document == NULL\n");
2515#endif
2516 return(-1);
2517 }
2518 encoding = (const char *) cur->encoding;
2519
2520 if (encoding != NULL) {
2522 if (handler == NULL) {
2523 xmlFree((char *) cur->encoding);
2524 cur->encoding = NULL;
2525 encoding = NULL;
2526 }
2527 }
2528 buf = xmlOutputBufferCreateFile(f, handler);
2529 if (buf == NULL) return(-1);
2530 memset(&ctxt, 0, sizeof(ctxt));
2531 ctxt.buf = buf;
2532 ctxt.level = 0;
2533 ctxt.format = format ? 1 : 0;
2534 ctxt.encoding = (const xmlChar *) encoding;
2535 xmlSaveCtxtInit(&ctxt);
2536 ctxt.options |= XML_SAVE_AS_XML;
2537 xmlDocContentDumpOutput(&ctxt, cur);
2538
2539 ret = xmlOutputBufferClose(buf);
2540 return(ret);
2541}
2542
2552int
2553xmlDocDump(FILE *f, xmlDocPtr cur) {
2554 return(xmlDocFormatDump (f, cur, 0));
2555}
2556
2569int
2570xmlSaveFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding) {
2571 xmlSaveCtxt ctxt;
2572 int ret;
2573
2574 if (buf == NULL) return(-1);
2575 if (cur == NULL) {
2576 xmlOutputBufferClose(buf);
2577 return(-1);
2578 }
2579 memset(&ctxt, 0, sizeof(ctxt));
2580 ctxt.buf = buf;
2581 ctxt.level = 0;
2582 ctxt.format = 0;
2583 ctxt.encoding = (const xmlChar *) encoding;
2584 xmlSaveCtxtInit(&ctxt);
2585 ctxt.options |= XML_SAVE_AS_XML;
2586 xmlDocContentDumpOutput(&ctxt, cur);
2587 ret = xmlOutputBufferClose(buf);
2588 return(ret);
2589}
2590
2604int
2605xmlSaveFormatFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur,
2606 const char *encoding, int format)
2607{
2608 xmlSaveCtxt ctxt;
2609 int ret;
2610
2611 if (buf == NULL) return(-1);
2612 if ((cur == NULL) ||
2613 ((cur->type != XML_DOCUMENT_NODE) &&
2614 (cur->type != XML_HTML_DOCUMENT_NODE))) {
2615 xmlOutputBufferClose(buf);
2616 return(-1);
2617 }
2618 memset(&ctxt, 0, sizeof(ctxt));
2619 ctxt.buf = buf;
2620 ctxt.level = 0;
2621 ctxt.format = format ? 1 : 0;
2622 ctxt.encoding = (const xmlChar *) encoding;
2623 xmlSaveCtxtInit(&ctxt);
2624 ctxt.options |= XML_SAVE_AS_XML;
2625 xmlDocContentDumpOutput(&ctxt, cur);
2626 ret = xmlOutputBufferClose(buf);
2627 return (ret);
2628}
2629
2643int
2644xmlSaveFormatFileEnc( const char * filename, xmlDocPtr cur,
2645 const char * encoding, int format ) {
2646 xmlSaveCtxt ctxt;
2649 int ret;
2650
2651 if (cur == NULL)
2652 return(-1);
2653
2654 if (encoding == NULL)
2655 encoding = (const char *) cur->encoding;
2656
2657 if (encoding != NULL) {
2658
2660 if (handler == NULL)
2661 return(-1);
2662 }
2663
2664#ifdef LIBXML_ZLIB_ENABLED
2665 if (cur->compression < 0) cur->compression = xmlGetCompressMode();
2666#endif
2667 /*
2668 * save the content to a temp buffer.
2669 */
2670 buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
2671 if (buf == NULL) return(-1);
2672 memset(&ctxt, 0, sizeof(ctxt));
2673 ctxt.buf = buf;
2674 ctxt.level = 0;
2675 ctxt.format = format ? 1 : 0;
2676 ctxt.encoding = (const xmlChar *) encoding;
2677 xmlSaveCtxtInit(&ctxt);
2678 ctxt.options |= XML_SAVE_AS_XML;
2679
2680 xmlDocContentDumpOutput(&ctxt, cur);
2681
2682 ret = xmlOutputBufferClose(buf);
2683 return(ret);
2684}
2685
2686
2697int
2698xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) {
2699 return ( xmlSaveFormatFileEnc( filename, cur, encoding, 0 ) );
2700}
2701
2716int
2717xmlSaveFormatFile(const char *filename, xmlDocPtr cur, int format) {
2718 return ( xmlSaveFormatFileEnc( filename, cur, NULL, format ) );
2719}
2720
2731int
2732xmlSaveFile(const char *filename, xmlDocPtr cur) {
2733 return(xmlSaveFormatFileEnc(filename, cur, NULL, 0));
2734}
2735
2736#endif /* LIBXML_OUTPUT_ENABLED */
2737
#define msg(x)
Definition: auth_time.c:54
struct _root root
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t compression
Definition: btrfs_drv.h:1365
xmlBufPtr xmlBufFromBuffer(xmlBufferPtr buffer)
Definition: buf.c:977
int xmlBufGetAllocationScheme(xmlBufPtr buf)
Definition: buf.c:260
void xmlBufFree(xmlBufPtr buf)
Definition: buf.c:322
xmlBufPtr xmlBufCreate(void)
Definition: buf.c:122
int xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer)
Definition: buf.c:1068
int xmlBufSetAllocationScheme(xmlBufPtr buf, xmlBufferAllocationScheme scheme)
Definition: buf.c:281
int xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string)
Definition: buf.c:921
xmlBufferPtr xmlBufBackToBuffer(xmlBufPtr buf)
Definition: buf.c:1013
int xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len)
Definition: buf.c:821
r l[0]
Definition: byte_order.h:168
#define NULL
Definition: types.h:112
static const WCHAR indent[]
Definition: object.c:1156
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7482
r parent
Definition: btrfs.c:3010
int xmlCharEncOutput(xmlOutputBufferPtr output, int init)
XMLPUBFUN int XMLCALL xmlCharEncCloseFunc(xmlCharEncodingHandler *handler)
Definition: encoding.c:2796
int(* xmlCharEncodingOutputFunc)(unsigned char *out, int *outlen, const unsigned char *in, int *inlen)
Definition: encoding.h:121
XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL xmlFindCharEncodingHandler(const char *name)
Definition: encoding.c:1678
xmlCharEncoding
Definition: encoding.h:56
@ XML_CHAR_ENCODING_UTF8
Definition: encoding.h:59
@ XML_CHAR_ENCODING_NONE
Definition: encoding.h:58
@ XML_CHAR_ENCODING_ASCII
Definition: encoding.h:80
XMLPUBFUN xmlCharEncoding XMLCALL xmlParseCharEncoding(const char *name)
Definition: encoding.c:1170
FxCollectionEntry * cur
GLuint start
Definition: gl.h:1545
GLint level
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLuint buffer
Definition: glext.h:5915
GLfloat f
Definition: glext.h:7540
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint in
Definition: glext.h:9616
GLuint GLfloat * val
Definition: glext.h:7180
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
@ extra
Definition: id3.c:95
#define INT_MAX
Definition: limits.h:40
const char * filename
Definition: ioapi.h:137
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
static size_t elem
Definition: string.c:68
static HWND child
Definition: cursoricon.c:298
static WCHAR escape[]
Definition: url.c:36
#define IS_CHAR(c)
XMLPUBVAR const xmlChar xmlStringTextNoenc[]
#define IS_BYTE_CHAR(c)
XMLPUBVAR const xmlChar xmlStringText[]
static FILE * out
Definition: regtests2xml.c:44
XMLPUBVAR int xmlSaveNoEmptyTags
Definition: globals.h:449
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:248
XMLPUBVAR int xmlIndentTreeOutput
Definition: globals.h:378
XMLPUBVAR const char * xmlTreeIndentString
Definition: globals.h:387
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
XMLPUBVAR void * xmlGenericErrorContext
Definition: globals.h:353
XMLPUBVAR xmlGenericErrorFunc xmlGenericError
Definition: globals.h:337
XMLPUBFUN void XMLCALL xmlInitParser(void)
Definition: parser.c:14676
XMLPUBFUN xmlChar *XMLCALL xmlGetProp(const xmlNode *node, const xmlChar *name)
xmlOutputBuffer * xmlOutputBufferPtr
Definition: tree.h:32
XMLPUBFUN size_t XMLCALL xmlBufUse(const xmlBufPtr buf)
Definition: buf.c:633
xmlNode * xmlNodePtr
Definition: tree.h:488
struct _xmlOutputBuffer xmlOutputBuffer
Definition: tree.h:31
XMLPUBFUN xmlDtdPtr XMLCALL xmlGetIntSubset(const xmlDoc *doc)
@ XML_ATTRIBUTE_NODE
Definition: tree.h:161
@ XML_ENTITY_DECL
Definition: tree.h:176
@ XML_DOCUMENT_NODE
Definition: tree.h:168
@ XML_CDATA_SECTION_NODE
Definition: tree.h:163
@ XML_TEXT_NODE
Definition: tree.h:162
@ XML_XINCLUDE_START
Definition: tree.h:178
@ XML_PI_NODE
Definition: tree.h:166
@ XML_XINCLUDE_END
Definition: tree.h:179
@ XML_DOCUMENT_FRAG_NODE
Definition: tree.h:170
@ XML_COMMENT_NODE
Definition: tree.h:167
@ XML_DTD_NODE
Definition: tree.h:173
@ XML_NAMESPACE_DECL
Definition: tree.h:177
@ XML_HTML_DOCUMENT_NODE
Definition: tree.h:172
@ XML_ELEMENT_NODE
Definition: tree.h:160
@ XML_ELEMENT_DECL
Definition: tree.h:174
@ XML_ENTITY_REF_NODE
Definition: tree.h:164
@ XML_ATTRIBUTE_DECL
Definition: tree.h:175
XMLPUBFUN int XMLCALL xmlGetCompressMode(void)
XMLPUBFUN xmlBufferPtr XMLCALL xmlBufferCreate(void)
@ XML_BUFFER_ALLOC_DOUBLEIT
Definition: tree.h:75
XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocText(const xmlDoc *doc, const xmlChar *content)
XMLPUBFUN void XMLCALL xmlFreeNode(xmlNodePtr cur)
XMLPUBFUN void XMLCALL xmlBufferSetAllocationScheme(xmlBufferPtr buf, xmlBufferAllocationScheme scheme)
XMLPUBFUN xmlChar *XMLCALL xmlBufContent(const xmlBuf *buf)
Definition: buf.c:553
#define XML_LOCAL_NAMESPACE
Definition: tree.h:374
static int fd
Definition: io.c:51
#define memset(x, y, z)
Definition: compat.h:39
Definition: tree.h:434
Definition: buf.c:43
Definition: tree.h:551
const xmlChar * encoding
Definition: tree.h:574
xmlElementType type
Definition: tree.h:553
Definition: tree.h:406
struct _xmlDoc * doc
Definition: tree.h:415
void * pentities
Definition: tree.h:424
const xmlChar * name
Definition: tree.h:409
void * elements
Definition: tree.h:419
void * entities
Definition: tree.h:421
struct _xmlNode * children
Definition: tree.h:410
void * notations
Definition: tree.h:418
const xmlChar * SystemID
Definition: tree.h:423
const xmlChar * ExternalID
Definition: tree.h:422
void * attributes
Definition: tree.h:420
Definition: tree.h:489
xmlChar * content
Definition: tree.h:502
struct _xmlNode * next
Definition: tree.h:496
const xmlChar * name
Definition: tree.h:492
xmlElementType type
Definition: tree.h:491
Definition: tree.h:389
Definition: cookie.c:202
Definition: inflate.c:139
Definition: mem.c:156
Definition: name.c:39
Definition: dlist.c:348
static const WCHAR lang[]
Definition: wbemdisp.c:287
int ret
@ XML_FROM_OUTPUT
Definition: xmlerror.h:44
@ XML_SAVE_CHAR_INVALID
Definition: xmlerror.h:414
@ XML_ERR_INTERNAL_ERROR
Definition: xmlerror.h:101
@ XML_SAVE_NOT_UTF8
Definition: xmlerror.h:413
@ XML_SAVE_NO_DOCTYPE
Definition: xmlerror.h:415
@ XML_SAVE_UNKNOWN_ENCODING
Definition: xmlerror.h:416
@ XML_ERR_NO_MEMORY
Definition: xmlerror.h:102
static char * encoding
Definition: xmllint.c:155
#define XHTML_TRANS_PUBLIC_ID
Definition: xmlsave.c:39
#define XHTML_FRAME_SYSTEM_ID
Definition: xmlsave.c:37
#define XHTML_STRICT_SYSTEM_ID
Definition: xmlsave.c:33
#define XHTML_FRAME_PUBLIC_ID
Definition: xmlsave.c:35
#define XHTML_TRANS_SYSTEM_ID
Definition: xmlsave.c:41
#define XHTML_STRICT_PUBLIC_ID
Definition: xmlsave.c:31
#define MAX_INDENT
Definition: xmlsave.c:18
int xmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID)
Definition: xmlsave.c:55
#define XHTML_NS_NAME
Definition: xmlsave.c:44
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:42
XMLPUBFUN int XMLCALL xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:275
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:67
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:426
unsigned char xmlChar
Definition: xmlstring.h:28