ReactOS 0.4.16-dev-2232-gc2aaa52
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 "private/buf.h"
23#include "private/enc.h"
24#include "private/error.h"
25#include "private/save.h"
26
27#ifdef LIBXML_OUTPUT_ENABLED
28
29#define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml"
30
31#define TODO \
32 xmlGenericError(xmlGenericErrorContext, \
33 "Unimplemented block at %s:%d\n", \
34 __FILE__, __LINE__);
35
36struct _xmlSaveCtxt {
37 void *_private;
38 int type;
39 int fd;
40 const xmlChar *filename;
41 const xmlChar *encoding;
43 xmlOutputBufferPtr buf;
44 int options;
45 int level;
46 int format;
47 char indent[MAX_INDENT + 1]; /* array for indenting output */
48 int indent_nr;
49 int indent_size;
50 xmlCharEncodingOutputFunc escape; /* used for element content */
51 xmlCharEncodingOutputFunc escapeAttr;/* used for attribute content */
52};
53
54/************************************************************************
55 * *
56 * Output error handlers *
57 * *
58 ************************************************************************/
65static void
66xmlSaveErrMemory(const char *extra)
67{
69}
70
79static void
80xmlSaveErr(int code, xmlNodePtr node, const char *extra)
81{
82 const char *msg = NULL;
83
84 switch(code) {
86 msg = "string is not in UTF-8\n";
87 break;
89 msg = "invalid character value\n";
90 break;
92 msg = "unknown encoding %s\n";
93 break;
95 msg = "document has no DOCTYPE\n";
96 break;
97 default:
98 msg = "unexpected error number\n";
99 }
101}
102
103/************************************************************************
104 * *
105 * Special escaping routines *
106 * *
107 ************************************************************************/
108static unsigned char *
109xmlSerializeHexCharRef(unsigned char *out, int val) {
110 unsigned char *ptr;
111
112 *out++ = '&';
113 *out++ = '#';
114 *out++ = 'x';
115 if (val < 0x10) ptr = out;
116 else if (val < 0x100) ptr = out + 1;
117 else if (val < 0x1000) ptr = out + 2;
118 else if (val < 0x10000) ptr = out + 3;
119 else if (val < 0x100000) ptr = out + 4;
120 else ptr = out + 5;
121 out = ptr + 1;
122 while (val > 0) {
123 switch (val & 0xF) {
124 case 0: *ptr-- = '0'; break;
125 case 1: *ptr-- = '1'; break;
126 case 2: *ptr-- = '2'; break;
127 case 3: *ptr-- = '3'; break;
128 case 4: *ptr-- = '4'; break;
129 case 5: *ptr-- = '5'; break;
130 case 6: *ptr-- = '6'; break;
131 case 7: *ptr-- = '7'; break;
132 case 8: *ptr-- = '8'; break;
133 case 9: *ptr-- = '9'; break;
134 case 0xA: *ptr-- = 'A'; break;
135 case 0xB: *ptr-- = 'B'; break;
136 case 0xC: *ptr-- = 'C'; break;
137 case 0xD: *ptr-- = 'D'; break;
138 case 0xE: *ptr-- = 'E'; break;
139 case 0xF: *ptr-- = 'F'; break;
140 default: *ptr-- = '0'; break;
141 }
142 val >>= 4;
143 }
144 *out++ = ';';
145 *out = 0;
146 return(out);
147}
148
164static int
165xmlEscapeEntities(unsigned char* out, int *outlen,
166 const xmlChar* in, int *inlen) {
167 unsigned char* outstart = out;
168 const unsigned char* base = in;
169 unsigned char* outend = out + *outlen;
170 const unsigned char* inend;
171 int val;
172
173 inend = in + (*inlen);
174
175 while ((in < inend) && (out < outend)) {
176 if (*in == '<') {
177 if (outend - out < 4) break;
178 *out++ = '&';
179 *out++ = 'l';
180 *out++ = 't';
181 *out++ = ';';
182 in++;
183 continue;
184 } else if (*in == '>') {
185 if (outend - out < 4) break;
186 *out++ = '&';
187 *out++ = 'g';
188 *out++ = 't';
189 *out++ = ';';
190 in++;
191 continue;
192 } else if (*in == '&') {
193 if (outend - out < 5) break;
194 *out++ = '&';
195 *out++ = 'a';
196 *out++ = 'm';
197 *out++ = 'p';
198 *out++ = ';';
199 in++;
200 continue;
201 } else if (((*in >= 0x20) && (*in < 0x80)) ||
202 (*in == '\n') || (*in == '\t')) {
203 /*
204 * default case, just copy !
205 */
206 *out++ = *in++;
207 continue;
208 } else if (*in >= 0x80) {
209 /*
210 * We assume we have UTF-8 input.
211 */
212 if (outend - out < 11) break;
213
214 if (*in < 0xC0) {
215 xmlSaveErr(XML_SAVE_NOT_UTF8, NULL, NULL);
216 in++;
217 goto error;
218 } else if (*in < 0xE0) {
219 if (inend - in < 2) break;
220 val = (in[0]) & 0x1F;
221 val <<= 6;
222 val |= (in[1]) & 0x3F;
223 in += 2;
224 } else if (*in < 0xF0) {
225 if (inend - in < 3) break;
226 val = (in[0]) & 0x0F;
227 val <<= 6;
228 val |= (in[1]) & 0x3F;
229 val <<= 6;
230 val |= (in[2]) & 0x3F;
231 in += 3;
232 } else if (*in < 0xF8) {
233 if (inend - in < 4) break;
234 val = (in[0]) & 0x07;
235 val <<= 6;
236 val |= (in[1]) & 0x3F;
237 val <<= 6;
238 val |= (in[2]) & 0x3F;
239 val <<= 6;
240 val |= (in[3]) & 0x3F;
241 in += 4;
242 } else {
243 xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL);
244 in++;
245 goto error;
246 }
247 if (!IS_CHAR(val)) {
248 xmlSaveErr(XML_SAVE_CHAR_INVALID, NULL, NULL);
249 in++;
250 goto error;
251 }
252
253 /*
254 * We could do multiple things here. Just save as a char ref
255 */
256 out = xmlSerializeHexCharRef(out, val);
257 } else if (IS_BYTE_CHAR(*in)) {
258 if (outend - out < 6) break;
259 out = xmlSerializeHexCharRef(out, *in++);
260 } else {
262 "xmlEscapeEntities : char out of range\n");
263 in++;
264 goto error;
265 }
266 }
267 *outlen = out - outstart;
268 *inlen = in - base;
269 return(0);
270error:
271 *outlen = out - outstart;
272 *inlen = in - base;
273 return(-1);
274}
275
276/************************************************************************
277 * *
278 * Allocation and deallocation *
279 * *
280 ************************************************************************/
287static void
288xmlSaveCtxtInit(xmlSaveCtxtPtr ctxt)
289{
290 int i;
291 int len;
292
293 if (ctxt == NULL) return;
294 if ((ctxt->encoding == NULL) && (ctxt->escape == NULL))
295 ctxt->escape = xmlEscapeEntities;
296 len = xmlStrlen((xmlChar *)xmlTreeIndentString);
297 if ((xmlTreeIndentString == NULL) || (len == 0)) {
298 memset(&ctxt->indent[0], 0, MAX_INDENT + 1);
299 } else {
300 ctxt->indent_size = len;
301 ctxt->indent_nr = MAX_INDENT / ctxt->indent_size;
302 for (i = 0;i < ctxt->indent_nr;i++)
303 memcpy(&ctxt->indent[i * ctxt->indent_size], xmlTreeIndentString,
304 ctxt->indent_size);
305 ctxt->indent[ctxt->indent_nr * ctxt->indent_size] = 0;
306 }
307
308 if (xmlSaveNoEmptyTags) {
309 ctxt->options |= XML_SAVE_NO_EMPTY;
310 }
311}
312
318static void
319xmlFreeSaveCtxt(xmlSaveCtxtPtr ctxt)
320{
321 if (ctxt == NULL) return;
322 if (ctxt->encoding != NULL)
323 xmlFree((char *) ctxt->encoding);
324 if (ctxt->buf != NULL)
325 xmlOutputBufferClose(ctxt->buf);
326 xmlFree(ctxt);
327}
328
336static xmlSaveCtxtPtr
337xmlNewSaveCtxt(const char *encoding, int options)
338{
339 xmlSaveCtxtPtr ret;
340
341 ret = (xmlSaveCtxtPtr) xmlMalloc(sizeof(xmlSaveCtxt));
342 if (ret == NULL) {
343 xmlSaveErrMemory("creating saving context");
344 return ( NULL );
345 }
346 memset(ret, 0, sizeof(xmlSaveCtxt));
347
348 if (encoding != NULL) {
349 ret->handler = xmlFindCharEncodingHandler(encoding);
350 if (ret->handler == NULL) {
351 xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL, encoding);
352 xmlFreeSaveCtxt(ret);
353 return(NULL);
354 }
355 ret->encoding = xmlStrdup((const xmlChar *)encoding);
356 ret->escape = NULL;
357 }
358 xmlSaveCtxtInit(ret);
359
360 /*
361 * Use the options
362 */
363
364 /* Re-check this option as it may already have been set */
365 if ((ret->options & XML_SAVE_NO_EMPTY) && ! (options & XML_SAVE_NO_EMPTY)) {
366 options |= XML_SAVE_NO_EMPTY;
367 }
368
369 ret->options = options;
370 if (options & XML_SAVE_FORMAT)
371 ret->format = 1;
372 else if (options & XML_SAVE_WSNONSIG)
373 ret->format = 2;
374
375 return(ret);
376}
377
378/************************************************************************
379 * *
380 * Dumping XML tree content to a simple buffer *
381 * *
382 ************************************************************************/
391static void
392xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr)
393{
394 xmlNodePtr children;
395
396 children = attr->children;
397 while (children != NULL) {
398 switch (children->type) {
399 case XML_TEXT_NODE:
400 xmlBufAttrSerializeTxtContent(buf->buffer, attr->doc,
401 attr, children->content);
402 break;
403 case XML_ENTITY_REF_NODE:
404 xmlBufAdd(buf->buffer, BAD_CAST "&", 1);
405 xmlBufAdd(buf->buffer, children->name,
406 xmlStrlen(children->name));
407 xmlBufAdd(buf->buffer, BAD_CAST ";", 1);
408 break;
409 default:
410 /* should not happen unless we have a badly built tree */
411 break;
412 }
413 children = children->next;
414 }
415}
416
424static void
425xmlBufDumpNotationTable(xmlBufPtr buf, xmlNotationTablePtr table) {
426 xmlBufferPtr buffer;
427
428 buffer = xmlBufferCreate();
429 if (buffer == NULL) {
430 /*
431 * TODO set the error in buf
432 */
433 return;
434 }
435 xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
436 xmlDumpNotationTable(buffer, table);
438}
439
448static void
449xmlBufDumpElementDecl(xmlBufPtr buf, xmlElementPtr elem) {
450 xmlBufferPtr buffer;
451
452 buffer = xmlBufferCreate();
453 if (buffer == NULL) {
454 /*
455 * TODO set the error in buf
456 */
457 return;
458 }
459 xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
460 xmlDumpElementDecl(buffer, elem);
462}
463
472static void
473xmlBufDumpAttributeDecl(xmlBufPtr buf, xmlAttributePtr attr) {
474 xmlBufferPtr buffer;
475
476 buffer = xmlBufferCreate();
477 if (buffer == NULL) {
478 /*
479 * TODO set the error in buf
480 */
481 return;
482 }
483 xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
484 xmlDumpAttributeDecl(buffer, attr);
486}
487
495static void
496xmlBufDumpEntityDecl(xmlBufPtr buf, xmlEntityPtr ent) {
497 xmlBufferPtr buffer;
498
499 buffer = xmlBufferCreate();
500 if (buffer == NULL) {
501 /*
502 * TODO set the error in buf
503 */
504 return;
505 }
506 xmlBufferSetAllocationScheme(buffer, XML_BUFFER_ALLOC_DOUBLEIT);
507 xmlDumpEntityDecl(buffer, ent);
509}
510
511/************************************************************************
512 * *
513 * Dumping XML tree content to an I/O output buffer *
514 * *
515 ************************************************************************/
516
517static int xmlSaveSwitchEncoding(xmlSaveCtxtPtr ctxt, const char *encoding) {
518 xmlOutputBufferPtr buf = ctxt->buf;
519
520 if ((encoding != NULL) && (buf->encoder == NULL) && (buf->conv == NULL)) {
521 buf->encoder = xmlFindCharEncodingHandler((const char *)encoding);
522 if (buf->encoder == NULL) {
524 (const char *)encoding);
525 return(-1);
526 }
527 buf->conv = xmlBufCreate();
528 if (buf->conv == NULL) {
529 xmlCharEncCloseFunc(buf->encoder);
530 xmlSaveErrMemory("creating encoding buffer");
531 return(-1);
532 }
533 /*
534 * initialize the state, e.g. if outputting a BOM
535 */
537 }
538 return(0);
539}
540
541static int xmlSaveClearEncoding(xmlSaveCtxtPtr ctxt) {
542 xmlOutputBufferPtr buf = ctxt->buf;
543 xmlOutputBufferFlush(buf);
544 xmlCharEncCloseFunc(buf->encoder);
545 xmlBufFree(buf->conv);
546 buf->encoder = NULL;
547 buf->conv = NULL;
548 return(0);
549}
550
551#ifdef LIBXML_HTML_ENABLED
552static void
553xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
554#endif
555static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
556static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur);
557
565static void
566xmlOutputBufferWriteWSNonSig(xmlSaveCtxtPtr ctxt, int extra)
567{
568 int i;
569 if ((ctxt == NULL) || (ctxt->buf == NULL))
570 return;
571 xmlOutputBufferWrite(ctxt->buf, 1, "\n");
572 for (i = 0; i < (ctxt->level + extra); i += ctxt->indent_nr) {
573 xmlOutputBufferWrite(ctxt->buf, ctxt->indent_size *
574 ((ctxt->level + extra - i) > ctxt->indent_nr ?
575 ctxt->indent_nr : (ctxt->level + extra - i)),
576 ctxt->indent);
577 }
578}
579
590static void
591xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur, xmlSaveCtxtPtr ctxt) {
592 if ((cur == NULL) || (buf == NULL)) return;
593 if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) {
594 if (xmlStrEqual(cur->prefix, BAD_CAST "xml"))
595 return;
596
597 if (ctxt != NULL && ctxt->format == 2)
598 xmlOutputBufferWriteWSNonSig(ctxt, 2);
599 else
600 xmlOutputBufferWrite(buf, 1, " ");
601
602 /* Within the context of an element attributes */
603 if (cur->prefix != NULL) {
604 xmlOutputBufferWrite(buf, 6, "xmlns:");
605 xmlOutputBufferWriteString(buf, (const char *)cur->prefix);
606 } else
607 xmlOutputBufferWrite(buf, 5, "xmlns");
608 xmlOutputBufferWrite(buf, 1, "=");
609 xmlBufWriteQuotedString(buf->buffer, cur->href);
610 }
611}
612
621static void
622xmlNsDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
623 xmlNsDumpOutput(ctxt->buf, cur, ctxt);
624}
625
634static void
635xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
636 while (cur != NULL) {
637 xmlNsDumpOutput(ctxt->buf, cur, ctxt);
638 cur = cur->next;
639 }
640}
641
650void
651xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
652 while (cur != NULL) {
653 xmlNsDumpOutput(buf, cur, NULL);
654 cur = cur->next;
655 }
656}
657
665static void
666xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt, xmlDtdPtr dtd) {
667 xmlOutputBufferPtr buf;
668 xmlNodePtr cur;
669 int format, level;
670
671 if (dtd == NULL) return;
672 if ((ctxt == NULL) || (ctxt->buf == NULL))
673 return;
674 buf = ctxt->buf;
675 xmlOutputBufferWrite(buf, 10, "<!DOCTYPE ");
676 xmlOutputBufferWriteString(buf, (const char *)dtd->name);
677 if (dtd->ExternalID != NULL) {
678 xmlOutputBufferWrite(buf, 8, " PUBLIC ");
679 xmlBufWriteQuotedString(buf->buffer, dtd->ExternalID);
680 xmlOutputBufferWrite(buf, 1, " ");
681 xmlBufWriteQuotedString(buf->buffer, dtd->SystemID);
682 } else if (dtd->SystemID != NULL) {
683 xmlOutputBufferWrite(buf, 8, " SYSTEM ");
684 xmlBufWriteQuotedString(buf->buffer, dtd->SystemID);
685 }
686 if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
687 (dtd->attributes == NULL) && (dtd->notations == NULL) &&
688 (dtd->pentities == NULL)) {
689 xmlOutputBufferWrite(buf, 1, ">");
690 return;
691 }
692 xmlOutputBufferWrite(buf, 3, " [\n");
693 /*
694 * Dump the notations first they are not in the DTD children list
695 * Do this only on a standalone DTD or on the internal subset though.
696 */
697 if ((dtd->notations != NULL) && ((dtd->doc == NULL) ||
698 (dtd->doc->intSubset == dtd))) {
699 xmlBufDumpNotationTable(buf->buffer,
700 (xmlNotationTablePtr) dtd->notations);
701 }
702 format = ctxt->format;
703 level = ctxt->level;
704 ctxt->format = 0;
705 ctxt->level = -1;
706 for (cur = dtd->children; cur != NULL; cur = cur->next) {
707 xmlNodeDumpOutputInternal(ctxt, cur);
708 }
709 ctxt->format = format;
710 ctxt->level = level;
711 xmlOutputBufferWrite(buf, 2, "]>");
712}
713
721static void
722xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
723 xmlOutputBufferPtr buf;
724
725 if (cur == NULL) return;
726 buf = ctxt->buf;
727 if (buf == NULL) return;
728 if (ctxt->format == 2)
729 xmlOutputBufferWriteWSNonSig(ctxt, 2);
730 else
731 xmlOutputBufferWrite(buf, 1, " ");
732 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
733 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
734 xmlOutputBufferWrite(buf, 1, ":");
735 }
736 xmlOutputBufferWriteString(buf, (const char *)cur->name);
737 xmlOutputBufferWrite(buf, 2, "=\"");
738 xmlAttrSerializeContent(buf, cur);
739 xmlOutputBufferWrite(buf, 1, "\"");
740}
741
742#ifdef LIBXML_HTML_ENABLED
749static int
750htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
751 const xmlChar *oldenc = NULL;
752 const xmlChar *oldctxtenc = ctxt->encoding;
753 const xmlChar *encoding = ctxt->encoding;
754 xmlOutputBufferPtr buf = ctxt->buf;
755 int switched_encoding = 0;
756 xmlDocPtr doc;
757
759
760 doc = cur->doc;
761 if (doc != NULL) {
762 oldenc = doc->encoding;
763 if (ctxt->encoding != NULL) {
764 doc->encoding = BAD_CAST ctxt->encoding;
765 } else if (doc->encoding != NULL) {
766 encoding = doc->encoding;
767 }
768 }
769
770 if ((encoding != NULL) && (doc != NULL))
771 htmlSetMetaEncoding(doc, (const xmlChar *) encoding);
772 if ((encoding == NULL) && (doc != NULL))
773 encoding = htmlGetMetaEncoding(doc);
774 if (encoding == NULL)
775 encoding = BAD_CAST "HTML";
776 if ((encoding != NULL) && (oldctxtenc == NULL) &&
777 (buf->encoder == NULL) && (buf->conv == NULL)) {
778 if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
779 doc->encoding = oldenc;
780 return(-1);
781 }
782 switched_encoding = 1;
783 }
784 if (ctxt->options & XML_SAVE_FORMAT)
785 htmlNodeDumpFormatOutput(buf, doc, cur,
786 (const char *)encoding, 1);
787 else
788 htmlNodeDumpFormatOutput(buf, doc, cur,
789 (const char *)encoding, 0);
790 /*
791 * Restore the state of the saving context at the end of the document
792 */
793 if ((switched_encoding) && (oldctxtenc == NULL)) {
794 xmlSaveClearEncoding(ctxt);
795 }
796 if (doc != NULL)
797 doc->encoding = oldenc;
798 return(0);
799}
800#endif
801
808static void
809xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
810 int format = ctxt->format;
811 xmlNodePtr tmp, root, unformattedNode = NULL, parent;
812 xmlAttrPtr attr;
813 xmlChar *start, *end;
814 xmlOutputBufferPtr buf;
815
816 if (cur == NULL) return;
817 buf = ctxt->buf;
818
819 root = cur;
820 parent = cur->parent;
821 while (1) {
822 switch (cur->type) {
823 case XML_DOCUMENT_NODE:
824 case XML_HTML_DOCUMENT_NODE:
825 xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
826 break;
827
828 case XML_DTD_NODE:
829 xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
830 break;
831
832 case XML_DOCUMENT_FRAG_NODE:
833 /* Always validate cur->parent when descending. */
834 if ((cur->parent == parent) && (cur->children != NULL)) {
835 parent = cur;
836 cur = cur->children;
837 continue;
838 }
839 break;
840
841 case XML_ELEMENT_DECL:
842 xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
843 break;
844
845 case XML_ATTRIBUTE_DECL:
846 xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
847 break;
848
849 case XML_ENTITY_DECL:
850 xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
851 break;
852
853 case XML_ELEMENT_NODE:
854 if ((cur != root) && (ctxt->format == 1) &&
855 (xmlIndentTreeOutput))
856 xmlOutputBufferWrite(buf, ctxt->indent_size *
857 (ctxt->level > ctxt->indent_nr ?
858 ctxt->indent_nr : ctxt->level),
859 ctxt->indent);
860
861 /*
862 * Some users like lxml are known to pass nodes with a corrupted
863 * tree structure. Fall back to a recursive call to handle this
864 * case.
865 */
866 if ((cur->parent != parent) && (cur->children != NULL)) {
867 xmlNodeDumpOutputInternal(ctxt, cur);
868 break;
869 }
870
871 xmlOutputBufferWrite(buf, 1, "<");
872 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
873 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
874 xmlOutputBufferWrite(buf, 1, ":");
875 }
876 xmlOutputBufferWriteString(buf, (const char *)cur->name);
877 if (cur->nsDef)
878 xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
879 for (attr = cur->properties; attr != NULL; attr = attr->next)
880 xmlAttrDumpOutput(ctxt, attr);
881
882 if (cur->children == NULL) {
883 if ((ctxt->options & XML_SAVE_NO_EMPTY) == 0) {
884 if (ctxt->format == 2)
885 xmlOutputBufferWriteWSNonSig(ctxt, 0);
886 xmlOutputBufferWrite(buf, 2, "/>");
887 } else {
888 if (ctxt->format == 2)
889 xmlOutputBufferWriteWSNonSig(ctxt, 1);
890 xmlOutputBufferWrite(buf, 3, "></");
891 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
892 xmlOutputBufferWriteString(buf,
893 (const char *)cur->ns->prefix);
894 xmlOutputBufferWrite(buf, 1, ":");
895 }
896 xmlOutputBufferWriteString(buf, (const char *)cur->name);
897 if (ctxt->format == 2)
898 xmlOutputBufferWriteWSNonSig(ctxt, 0);
899 xmlOutputBufferWrite(buf, 1, ">");
900 }
901 } else {
902 if (ctxt->format == 1) {
903 tmp = cur->children;
904 while (tmp != NULL) {
905 if ((tmp->type == XML_TEXT_NODE) ||
906 (tmp->type == XML_CDATA_SECTION_NODE) ||
907 (tmp->type == XML_ENTITY_REF_NODE)) {
908 ctxt->format = 0;
909 unformattedNode = cur;
910 break;
911 }
912 tmp = tmp->next;
913 }
914 }
915 if (ctxt->format == 2)
916 xmlOutputBufferWriteWSNonSig(ctxt, 1);
917 xmlOutputBufferWrite(buf, 1, ">");
918 if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
919 if (ctxt->level >= 0) ctxt->level++;
920 parent = cur;
921 cur = cur->children;
922 continue;
923 }
924
925 break;
926
927 case XML_TEXT_NODE:
928 if (cur->content == NULL)
929 break;
930 if (cur->name != xmlStringTextNoenc) {
931 xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
932 } else {
933 /*
934 * Disable escaping, needed for XSLT
935 */
936 xmlOutputBufferWriteString(buf, (const char *) cur->content);
937 }
938 break;
939
940 case XML_PI_NODE:
941 if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
942 xmlOutputBufferWrite(buf, ctxt->indent_size *
943 (ctxt->level > ctxt->indent_nr ?
944 ctxt->indent_nr : ctxt->level),
945 ctxt->indent);
946
947 if (cur->content != NULL) {
948 xmlOutputBufferWrite(buf, 2, "<?");
949 xmlOutputBufferWriteString(buf, (const char *)cur->name);
950 if (cur->content != NULL) {
951 if (ctxt->format == 2)
952 xmlOutputBufferWriteWSNonSig(ctxt, 0);
953 else
954 xmlOutputBufferWrite(buf, 1, " ");
955 xmlOutputBufferWriteString(buf,
956 (const char *)cur->content);
957 }
958 xmlOutputBufferWrite(buf, 2, "?>");
959 } else {
960 xmlOutputBufferWrite(buf, 2, "<?");
961 xmlOutputBufferWriteString(buf, (const char *)cur->name);
962 if (ctxt->format == 2)
963 xmlOutputBufferWriteWSNonSig(ctxt, 0);
964 xmlOutputBufferWrite(buf, 2, "?>");
965 }
966 break;
967
968 case XML_COMMENT_NODE:
969 if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
970 xmlOutputBufferWrite(buf, ctxt->indent_size *
971 (ctxt->level > ctxt->indent_nr ?
972 ctxt->indent_nr : ctxt->level),
973 ctxt->indent);
974
975 if (cur->content != NULL) {
976 xmlOutputBufferWrite(buf, 4, "<!--");
977 xmlOutputBufferWriteString(buf, (const char *)cur->content);
978 xmlOutputBufferWrite(buf, 3, "-->");
979 }
980 break;
981
982 case XML_ENTITY_REF_NODE:
983 xmlOutputBufferWrite(buf, 1, "&");
984 xmlOutputBufferWriteString(buf, (const char *)cur->name);
985 xmlOutputBufferWrite(buf, 1, ";");
986 break;
987
988 case XML_CDATA_SECTION_NODE:
989 if (cur->content == NULL || *cur->content == '\0') {
990 xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
991 } else {
992 start = end = cur->content;
993 while (*end != '\0') {
994 if ((*end == ']') && (*(end + 1) == ']') &&
995 (*(end + 2) == '>')) {
996 end = end + 2;
997 xmlOutputBufferWrite(buf, 9, "<![CDATA[");
998 xmlOutputBufferWrite(buf, end - start,
999 (const char *)start);
1000 xmlOutputBufferWrite(buf, 3, "]]>");
1001 start = end;
1002 }
1003 end++;
1004 }
1005 if (start != end) {
1006 xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1007 xmlOutputBufferWriteString(buf, (const char *)start);
1008 xmlOutputBufferWrite(buf, 3, "]]>");
1009 }
1010 }
1011 break;
1012
1013 case XML_ATTRIBUTE_NODE:
1014 xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
1015 break;
1016
1017 case XML_NAMESPACE_DECL:
1018 xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
1019 break;
1020
1021 default:
1022 break;
1023 }
1024
1025 while (1) {
1026 if (cur == root)
1027 return;
1028 if ((ctxt->format == 1) &&
1029 (cur->type != XML_XINCLUDE_START) &&
1030 (cur->type != XML_XINCLUDE_END))
1031 xmlOutputBufferWrite(buf, 1, "\n");
1032 if (cur->next != NULL) {
1033 cur = cur->next;
1034 break;
1035 }
1036
1037 cur = parent;
1038 /* cur->parent was validated when descending. */
1039 parent = cur->parent;
1040
1041 if (cur->type == XML_ELEMENT_NODE) {
1042 if (ctxt->level > 0) ctxt->level--;
1043 if ((xmlIndentTreeOutput) && (ctxt->format == 1))
1044 xmlOutputBufferWrite(buf, ctxt->indent_size *
1045 (ctxt->level > ctxt->indent_nr ?
1046 ctxt->indent_nr : ctxt->level),
1047 ctxt->indent);
1048
1049 xmlOutputBufferWrite(buf, 2, "</");
1050 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1051 xmlOutputBufferWriteString(buf,
1052 (const char *)cur->ns->prefix);
1053 xmlOutputBufferWrite(buf, 1, ":");
1054 }
1055
1056 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1057 if (ctxt->format == 2)
1058 xmlOutputBufferWriteWSNonSig(ctxt, 0);
1059 xmlOutputBufferWrite(buf, 1, ">");
1060
1061 if (cur == unformattedNode) {
1062 ctxt->format = format;
1063 unformattedNode = NULL;
1064 }
1065 }
1066 }
1067 }
1068}
1069
1076static int
1077xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
1078#ifdef LIBXML_HTML_ENABLED
1079 xmlDtdPtr dtd;
1080 int is_xhtml = 0;
1081#endif
1082 const xmlChar *oldenc = cur->encoding;
1083 const xmlChar *oldctxtenc = ctxt->encoding;
1084 const xmlChar *encoding = ctxt->encoding;
1085 xmlCharEncodingOutputFunc oldescape = ctxt->escape;
1086 xmlCharEncodingOutputFunc oldescapeAttr = ctxt->escapeAttr;
1087 xmlOutputBufferPtr buf = ctxt->buf;
1088 xmlCharEncoding enc;
1089 int switched_encoding = 0;
1090
1091 xmlInitParser();
1092
1093 if ((cur->type != XML_HTML_DOCUMENT_NODE) &&
1094 (cur->type != XML_DOCUMENT_NODE))
1095 return(-1);
1096
1097 if (ctxt->encoding != NULL) {
1098 cur->encoding = BAD_CAST ctxt->encoding;
1099 } else if (cur->encoding != NULL) {
1100 encoding = cur->encoding;
1101 }
1102
1103 if (((cur->type == XML_HTML_DOCUMENT_NODE) &&
1104 ((ctxt->options & XML_SAVE_AS_XML) == 0) &&
1105 ((ctxt->options & XML_SAVE_XHTML) == 0)) ||
1106 (ctxt->options & XML_SAVE_AS_HTML)) {
1107#ifdef LIBXML_HTML_ENABLED
1108 if (encoding != NULL)
1109 htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
1110 if (encoding == NULL)
1111 encoding = htmlGetMetaEncoding(cur);
1112 if (encoding == NULL)
1113 encoding = BAD_CAST "HTML";
1114 if ((encoding != NULL) && (oldctxtenc == NULL) &&
1115 (buf->encoder == NULL) && (buf->conv == NULL)) {
1116 if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
1117 cur->encoding = oldenc;
1118 return(-1);
1119 }
1120 }
1121 if (ctxt->options & XML_SAVE_FORMAT)
1122 htmlDocContentDumpFormatOutput(buf, cur,
1123 (const char *)encoding, 1);
1124 else
1125 htmlDocContentDumpFormatOutput(buf, cur,
1126 (const char *)encoding, 0);
1127 if (ctxt->encoding != NULL)
1128 cur->encoding = oldenc;
1129 return(0);
1130#else
1131 return(-1);
1132#endif
1133 } else if ((cur->type == XML_DOCUMENT_NODE) ||
1134 (ctxt->options & XML_SAVE_AS_XML) ||
1135 (ctxt->options & XML_SAVE_XHTML)) {
1136 enc = xmlParseCharEncoding((const char*) encoding);
1137 if ((encoding != NULL) && (oldctxtenc == NULL) &&
1138 (buf->encoder == NULL) && (buf->conv == NULL) &&
1139 ((ctxt->options & XML_SAVE_NO_DECL) == 0)) {
1140 if ((enc != XML_CHAR_ENCODING_UTF8) &&
1141 (enc != XML_CHAR_ENCODING_NONE) &&
1142 (enc != XML_CHAR_ENCODING_ASCII)) {
1143 /*
1144 * we need to switch to this encoding but just for this
1145 * document since we output the XMLDecl the conversion
1146 * must be done to not generate not well formed documents.
1147 */
1148 if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
1149 cur->encoding = oldenc;
1150 return(-1);
1151 }
1152 switched_encoding = 1;
1153 }
1154 if (ctxt->escape == xmlEscapeEntities)
1155 ctxt->escape = NULL;
1156 if (ctxt->escapeAttr == xmlEscapeEntities)
1157 ctxt->escapeAttr = NULL;
1158 }
1159
1160
1161 /*
1162 * Save the XML declaration
1163 */
1164 if ((ctxt->options & XML_SAVE_NO_DECL) == 0) {
1165 xmlOutputBufferWrite(buf, 14, "<?xml version=");
1166 if (cur->version != NULL)
1167 xmlBufWriteQuotedString(buf->buffer, cur->version);
1168 else
1169 xmlOutputBufferWrite(buf, 5, "\"1.0\"");
1170 if (encoding != NULL) {
1171 xmlOutputBufferWrite(buf, 10, " encoding=");
1172 xmlBufWriteQuotedString(buf->buffer, (xmlChar *) encoding);
1173 }
1174 switch (cur->standalone) {
1175 case 0:
1176 xmlOutputBufferWrite(buf, 16, " standalone=\"no\"");
1177 break;
1178 case 1:
1179 xmlOutputBufferWrite(buf, 17, " standalone=\"yes\"");
1180 break;
1181 }
1182 xmlOutputBufferWrite(buf, 3, "?>\n");
1183 }
1184
1185#ifdef LIBXML_HTML_ENABLED
1186 if (ctxt->options & XML_SAVE_XHTML)
1187 is_xhtml = 1;
1188 if ((ctxt->options & XML_SAVE_NO_XHTML) == 0) {
1189 dtd = xmlGetIntSubset(cur);
1190 if (dtd != NULL) {
1191 is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
1192 if (is_xhtml < 0) is_xhtml = 0;
1193 }
1194 }
1195#endif
1196 if (cur->children != NULL) {
1197 xmlNodePtr child = cur->children;
1198
1199 while (child != NULL) {
1200 ctxt->level = 0;
1201#ifdef LIBXML_HTML_ENABLED
1202 if (is_xhtml)
1203 xhtmlNodeDumpOutput(ctxt, child);
1204 else
1205#endif
1206 xmlNodeDumpOutputInternal(ctxt, child);
1207 if ((child->type != XML_XINCLUDE_START) &&
1208 (child->type != XML_XINCLUDE_END))
1209 xmlOutputBufferWrite(buf, 1, "\n");
1210 child = child->next;
1211 }
1212 }
1213 }
1214
1215 /*
1216 * Restore the state of the saving context at the end of the document
1217 */
1218 if ((switched_encoding) && (oldctxtenc == NULL)) {
1219 xmlSaveClearEncoding(ctxt);
1220 ctxt->escape = oldescape;
1221 ctxt->escapeAttr = oldescapeAttr;
1222 }
1223 cur->encoding = oldenc;
1224 return(0);
1225}
1226
1227#ifdef LIBXML_HTML_ENABLED
1228/************************************************************************
1229 * *
1230 * Functions specific to XHTML serialization *
1231 * *
1232 ************************************************************************/
1233
1242static int
1243xhtmlIsEmpty(xmlNodePtr node) {
1244 if (node == NULL)
1245 return(-1);
1246 if (node->type != XML_ELEMENT_NODE)
1247 return(0);
1248 if ((node->ns != NULL) && (!xmlStrEqual(node->ns->href, XHTML_NS_NAME)))
1249 return(0);
1250 if (node->children != NULL)
1251 return(0);
1252 switch (node->name[0]) {
1253 case 'a':
1254 if (xmlStrEqual(node->name, BAD_CAST "area"))
1255 return(1);
1256 return(0);
1257 case 'b':
1258 if (xmlStrEqual(node->name, BAD_CAST "br"))
1259 return(1);
1260 if (xmlStrEqual(node->name, BAD_CAST "base"))
1261 return(1);
1262 if (xmlStrEqual(node->name, BAD_CAST "basefont"))
1263 return(1);
1264 return(0);
1265 case 'c':
1266 if (xmlStrEqual(node->name, BAD_CAST "col"))
1267 return(1);
1268 return(0);
1269 case 'f':
1270 if (xmlStrEqual(node->name, BAD_CAST "frame"))
1271 return(1);
1272 return(0);
1273 case 'h':
1274 if (xmlStrEqual(node->name, BAD_CAST "hr"))
1275 return(1);
1276 return(0);
1277 case 'i':
1278 if (xmlStrEqual(node->name, BAD_CAST "img"))
1279 return(1);
1280 if (xmlStrEqual(node->name, BAD_CAST "input"))
1281 return(1);
1282 if (xmlStrEqual(node->name, BAD_CAST "isindex"))
1283 return(1);
1284 return(0);
1285 case 'l':
1286 if (xmlStrEqual(node->name, BAD_CAST "link"))
1287 return(1);
1288 return(0);
1289 case 'm':
1290 if (xmlStrEqual(node->name, BAD_CAST "meta"))
1291 return(1);
1292 return(0);
1293 case 'p':
1294 if (xmlStrEqual(node->name, BAD_CAST "param"))
1295 return(1);
1296 return(0);
1297 }
1298 return(0);
1299}
1300
1307static void
1308xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
1309 xmlAttrPtr xml_lang = NULL;
1310 xmlAttrPtr lang = NULL;
1311 xmlAttrPtr name = NULL;
1312 xmlAttrPtr id = NULL;
1313 xmlNodePtr parent;
1314 xmlOutputBufferPtr buf;
1315
1316 if (cur == NULL) return;
1317 buf = ctxt->buf;
1318 parent = cur->parent;
1319 while (cur != NULL) {
1320 if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "id")))
1321 id = cur;
1322 else
1323 if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "name")))
1324 name = cur;
1325 else
1326 if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")))
1327 lang = cur;
1328 else
1329 if ((cur->ns != NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")) &&
1330 (xmlStrEqual(cur->ns->prefix, BAD_CAST "xml")))
1331 xml_lang = cur;
1332 else if ((cur->ns == NULL) &&
1333 ((cur->children == NULL) ||
1334 (cur->children->content == NULL) ||
1335 (cur->children->content[0] == 0)) &&
1336 (htmlIsBooleanAttr(cur->name))) {
1337 if (cur->children != NULL)
1338 xmlFreeNode(cur->children);
1339 cur->children = xmlNewDocText(cur->doc, cur->name);
1340 if (cur->children != NULL)
1341 cur->children->parent = (xmlNodePtr) cur;
1342 }
1343 xmlAttrDumpOutput(ctxt, cur);
1344 cur = cur->next;
1345 }
1346 /*
1347 * C.8
1348 */
1349 if ((name != NULL) && (id == NULL)) {
1350 if ((parent != NULL) && (parent->name != NULL) &&
1351 ((xmlStrEqual(parent->name, BAD_CAST "a")) ||
1352 (xmlStrEqual(parent->name, BAD_CAST "p")) ||
1353 (xmlStrEqual(parent->name, BAD_CAST "div")) ||
1354 (xmlStrEqual(parent->name, BAD_CAST "img")) ||
1355 (xmlStrEqual(parent->name, BAD_CAST "map")) ||
1356 (xmlStrEqual(parent->name, BAD_CAST "applet")) ||
1357 (xmlStrEqual(parent->name, BAD_CAST "form")) ||
1358 (xmlStrEqual(parent->name, BAD_CAST "frame")) ||
1359 (xmlStrEqual(parent->name, BAD_CAST "iframe")))) {
1360 xmlOutputBufferWrite(buf, 5, " id=\"");
1361 xmlAttrSerializeContent(buf, name);
1362 xmlOutputBufferWrite(buf, 1, "\"");
1363 }
1364 }
1365 /*
1366 * C.7.
1367 */
1368 if ((lang != NULL) && (xml_lang == NULL)) {
1369 xmlOutputBufferWrite(buf, 11, " xml:lang=\"");
1370 xmlAttrSerializeContent(buf, lang);
1371 xmlOutputBufferWrite(buf, 1, "\"");
1372 } else
1373 if ((xml_lang != NULL) && (lang == NULL)) {
1374 xmlOutputBufferWrite(buf, 7, " lang=\"");
1375 xmlAttrSerializeContent(buf, xml_lang);
1376 xmlOutputBufferWrite(buf, 1, "\"");
1377 }
1378}
1379
1391static void
1392xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
1393 int format = ctxt->format, addmeta;
1394 xmlNodePtr tmp, root, unformattedNode = NULL, parent;
1395 xmlChar *start, *end;
1396 xmlOutputBufferPtr buf = ctxt->buf;
1397
1398 if (cur == NULL) return;
1399
1400 root = cur;
1401 parent = cur->parent;
1402 while (1) {
1403 switch (cur->type) {
1404 case XML_DOCUMENT_NODE:
1405 case XML_HTML_DOCUMENT_NODE:
1406 xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
1407 break;
1408
1409 case XML_NAMESPACE_DECL:
1410 xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur);
1411 break;
1412
1413 case XML_DTD_NODE:
1414 xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
1415 break;
1416
1417 case XML_DOCUMENT_FRAG_NODE:
1418 /* Always validate cur->parent when descending. */
1419 if ((cur->parent == parent) && (cur->children != NULL)) {
1420 parent = cur;
1421 cur = cur->children;
1422 continue;
1423 }
1424 break;
1425
1426 case XML_ELEMENT_DECL:
1427 xmlBufDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
1428 break;
1429
1430 case XML_ATTRIBUTE_DECL:
1431 xmlBufDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
1432 break;
1433
1434 case XML_ENTITY_DECL:
1435 xmlBufDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
1436 break;
1437
1438 case XML_ELEMENT_NODE:
1439 addmeta = 0;
1440
1441 if ((cur != root) && (ctxt->format == 1) && (xmlIndentTreeOutput))
1442 xmlOutputBufferWrite(buf, ctxt->indent_size *
1443 (ctxt->level > ctxt->indent_nr ?
1444 ctxt->indent_nr : ctxt->level),
1445 ctxt->indent);
1446
1447 /*
1448 * Some users like lxml are known to pass nodes with a corrupted
1449 * tree structure. Fall back to a recursive call to handle this
1450 * case.
1451 */
1452 if ((cur->parent != parent) && (cur->children != NULL)) {
1453 xhtmlNodeDumpOutput(ctxt, cur);
1454 break;
1455 }
1456
1457 xmlOutputBufferWrite(buf, 1, "<");
1458 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1459 xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
1460 xmlOutputBufferWrite(buf, 1, ":");
1461 }
1462
1463 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1464 if (cur->nsDef)
1465 xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
1466 if ((xmlStrEqual(cur->name, BAD_CAST "html") &&
1467 (cur->ns == NULL) && (cur->nsDef == NULL))) {
1468 /*
1469 * 3.1.1. Strictly Conforming Documents A.3.1.1 3/
1470 */
1471 xmlOutputBufferWriteString(buf,
1472 " xmlns=\"http://www.w3.org/1999/xhtml\"");
1473 }
1474 if (cur->properties != NULL)
1475 xhtmlAttrListDumpOutput(ctxt, cur->properties);
1476
1477 if ((parent != NULL) &&
1478 (parent->parent == (xmlNodePtr) cur->doc) &&
1479 xmlStrEqual(cur->name, BAD_CAST"head") &&
1480 xmlStrEqual(parent->name, BAD_CAST"html")) {
1481
1482 tmp = cur->children;
1483 while (tmp != NULL) {
1484 if (xmlStrEqual(tmp->name, BAD_CAST"meta")) {
1485 xmlChar *httpequiv;
1486
1487 httpequiv = xmlGetProp(tmp, BAD_CAST"http-equiv");
1488 if (httpequiv != NULL) {
1489 if (xmlStrcasecmp(httpequiv,
1490 BAD_CAST"Content-Type") == 0) {
1491 xmlFree(httpequiv);
1492 break;
1493 }
1494 xmlFree(httpequiv);
1495 }
1496 }
1497 tmp = tmp->next;
1498 }
1499 if (tmp == NULL)
1500 addmeta = 1;
1501 }
1502
1503 if (cur->children == NULL) {
1504 if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) &&
1505 ((xhtmlIsEmpty(cur) == 1) && (addmeta == 0))) {
1506 /*
1507 * C.2. Empty Elements
1508 */
1509 xmlOutputBufferWrite(buf, 3, " />");
1510 } else {
1511 if (addmeta == 1) {
1512 xmlOutputBufferWrite(buf, 1, ">");
1513 if (ctxt->format == 1) {
1514 xmlOutputBufferWrite(buf, 1, "\n");
1515 if (xmlIndentTreeOutput)
1516 xmlOutputBufferWrite(buf, ctxt->indent_size *
1517 (ctxt->level + 1 > ctxt->indent_nr ?
1518 ctxt->indent_nr : ctxt->level + 1),
1519 ctxt->indent);
1520 }
1521 xmlOutputBufferWriteString(buf,
1522 "<meta http-equiv=\"Content-Type\" "
1523 "content=\"text/html; charset=");
1524 if (ctxt->encoding) {
1525 xmlOutputBufferWriteString(buf,
1526 (const char *)ctxt->encoding);
1527 } else {
1528 xmlOutputBufferWrite(buf, 5, "UTF-8");
1529 }
1530 xmlOutputBufferWrite(buf, 4, "\" />");
1531 if (ctxt->format == 1)
1532 xmlOutputBufferWrite(buf, 1, "\n");
1533 } else {
1534 xmlOutputBufferWrite(buf, 1, ">");
1535 }
1536 /*
1537 * C.3. Element Minimization and Empty Element Content
1538 */
1539 xmlOutputBufferWrite(buf, 2, "</");
1540 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1541 xmlOutputBufferWriteString(buf,
1542 (const char *)cur->ns->prefix);
1543 xmlOutputBufferWrite(buf, 1, ":");
1544 }
1545 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1546 xmlOutputBufferWrite(buf, 1, ">");
1547 }
1548 } else {
1549 xmlOutputBufferWrite(buf, 1, ">");
1550 if (addmeta == 1) {
1551 if (ctxt->format == 1) {
1552 xmlOutputBufferWrite(buf, 1, "\n");
1553 if (xmlIndentTreeOutput)
1554 xmlOutputBufferWrite(buf, ctxt->indent_size *
1555 (ctxt->level + 1 > ctxt->indent_nr ?
1556 ctxt->indent_nr : ctxt->level + 1),
1557 ctxt->indent);
1558 }
1559 xmlOutputBufferWriteString(buf,
1560 "<meta http-equiv=\"Content-Type\" "
1561 "content=\"text/html; charset=");
1562 if (ctxt->encoding) {
1563 xmlOutputBufferWriteString(buf,
1564 (const char *)ctxt->encoding);
1565 } else {
1566 xmlOutputBufferWrite(buf, 5, "UTF-8");
1567 }
1568 xmlOutputBufferWrite(buf, 4, "\" />");
1569 }
1570
1571 if (ctxt->format == 1) {
1572 tmp = cur->children;
1573 while (tmp != NULL) {
1574 if ((tmp->type == XML_TEXT_NODE) ||
1575 (tmp->type == XML_ENTITY_REF_NODE)) {
1576 unformattedNode = cur;
1577 ctxt->format = 0;
1578 break;
1579 }
1580 tmp = tmp->next;
1581 }
1582 }
1583
1584 if (ctxt->format == 1) xmlOutputBufferWrite(buf, 1, "\n");
1585 if (ctxt->level >= 0) ctxt->level++;
1586 parent = cur;
1587 cur = cur->children;
1588 continue;
1589 }
1590
1591 break;
1592
1593 case XML_TEXT_NODE:
1594 if (cur->content == NULL)
1595 break;
1596 if ((cur->name == xmlStringText) ||
1597 (cur->name != xmlStringTextNoenc)) {
1598 xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
1599 } else {
1600 /*
1601 * Disable escaping, needed for XSLT
1602 */
1603 xmlOutputBufferWriteString(buf, (const char *) cur->content);
1604 }
1605 break;
1606
1607 case XML_PI_NODE:
1608 if (cur->content != NULL) {
1609 xmlOutputBufferWrite(buf, 2, "<?");
1610 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1611 if (cur->content != NULL) {
1612 xmlOutputBufferWrite(buf, 1, " ");
1613 xmlOutputBufferWriteString(buf,
1614 (const char *)cur->content);
1615 }
1616 xmlOutputBufferWrite(buf, 2, "?>");
1617 } else {
1618 xmlOutputBufferWrite(buf, 2, "<?");
1619 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1620 xmlOutputBufferWrite(buf, 2, "?>");
1621 }
1622 break;
1623
1624 case XML_COMMENT_NODE:
1625 if (cur->content != NULL) {
1626 xmlOutputBufferWrite(buf, 4, "<!--");
1627 xmlOutputBufferWriteString(buf, (const char *)cur->content);
1628 xmlOutputBufferWrite(buf, 3, "-->");
1629 }
1630 break;
1631
1632 case XML_ENTITY_REF_NODE:
1633 xmlOutputBufferWrite(buf, 1, "&");
1634 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1635 xmlOutputBufferWrite(buf, 1, ";");
1636 break;
1637
1638 case XML_CDATA_SECTION_NODE:
1639 if (cur->content == NULL || *cur->content == '\0') {
1640 xmlOutputBufferWrite(buf, 12, "<![CDATA[]]>");
1641 } else {
1642 start = end = cur->content;
1643 while (*end != '\0') {
1644 if (*end == ']' && *(end + 1) == ']' &&
1645 *(end + 2) == '>') {
1646 end = end + 2;
1647 xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1648 xmlOutputBufferWrite(buf, end - start,
1649 (const char *)start);
1650 xmlOutputBufferWrite(buf, 3, "]]>");
1651 start = end;
1652 }
1653 end++;
1654 }
1655 if (start != end) {
1656 xmlOutputBufferWrite(buf, 9, "<![CDATA[");
1657 xmlOutputBufferWriteString(buf, (const char *)start);
1658 xmlOutputBufferWrite(buf, 3, "]]>");
1659 }
1660 }
1661 break;
1662
1663 case XML_ATTRIBUTE_NODE:
1664 xmlAttrDumpOutput(ctxt, (xmlAttrPtr) cur);
1665 break;
1666
1667 default:
1668 break;
1669 }
1670
1671 while (1) {
1672 if (cur == root)
1673 return;
1674 if (ctxt->format == 1)
1675 xmlOutputBufferWrite(buf, 1, "\n");
1676 if (cur->next != NULL) {
1677 cur = cur->next;
1678 break;
1679 }
1680
1681 cur = parent;
1682 /* cur->parent was validated when descending. */
1683 parent = cur->parent;
1684
1685 if (cur->type == XML_ELEMENT_NODE) {
1686 if (ctxt->level > 0) ctxt->level--;
1687 if ((xmlIndentTreeOutput) && (ctxt->format == 1))
1688 xmlOutputBufferWrite(buf, ctxt->indent_size *
1689 (ctxt->level > ctxt->indent_nr ?
1690 ctxt->indent_nr : ctxt->level),
1691 ctxt->indent);
1692
1693 xmlOutputBufferWrite(buf, 2, "</");
1694 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
1695 xmlOutputBufferWriteString(buf,
1696 (const char *)cur->ns->prefix);
1697 xmlOutputBufferWrite(buf, 1, ":");
1698 }
1699
1700 xmlOutputBufferWriteString(buf, (const char *)cur->name);
1701 xmlOutputBufferWrite(buf, 1, ">");
1702
1703 if (cur == unformattedNode) {
1704 ctxt->format = format;
1705 unformattedNode = NULL;
1706 }
1707 }
1708 }
1709 }
1710}
1711#endif
1712
1713/************************************************************************
1714 * *
1715 * Public entry points *
1716 * *
1717 ************************************************************************/
1718
1730xmlSaveCtxtPtr
1731xmlSaveToFd(int fd, const char *encoding, int options)
1732{
1733 xmlSaveCtxtPtr ret;
1734
1735 ret = xmlNewSaveCtxt(encoding, options);
1736 if (ret == NULL) return(NULL);
1737 ret->buf = xmlOutputBufferCreateFd(fd, ret->handler);
1738 if (ret->buf == NULL) {
1739 xmlCharEncCloseFunc(ret->handler);
1740 xmlFreeSaveCtxt(ret);
1741 return(NULL);
1742 }
1743 return(ret);
1744}
1745
1758xmlSaveCtxtPtr
1759xmlSaveToFilename(const char *filename, const char *encoding, int options)
1760{
1761 xmlSaveCtxtPtr ret;
1762 int compression = 0; /* TODO handle compression option */
1763
1764 ret = xmlNewSaveCtxt(encoding, options);
1765 if (ret == NULL) return(NULL);
1766 ret->buf = xmlOutputBufferCreateFilename(filename, ret->handler,
1767 compression);
1768 if (ret->buf == NULL) {
1769 xmlCharEncCloseFunc(ret->handler);
1770 xmlFreeSaveCtxt(ret);
1771 return(NULL);
1772 }
1773 return(ret);
1774}
1775
1788xmlSaveCtxtPtr
1789xmlSaveToBuffer(xmlBufferPtr buffer, const char *encoding, int options)
1790{
1791 xmlSaveCtxtPtr ret;
1792
1793 ret = xmlNewSaveCtxt(encoding, options);
1794 if (ret == NULL) return(NULL);
1795 ret->buf = xmlOutputBufferCreateBuffer(buffer, ret->handler);
1796 if (ret->buf == NULL) {
1797 xmlCharEncCloseFunc(ret->handler);
1798 xmlFreeSaveCtxt(ret);
1799 return(NULL);
1800 }
1801 return(ret);
1802}
1803
1817xmlSaveCtxtPtr
1818xmlSaveToIO(xmlOutputWriteCallback iowrite,
1819 xmlOutputCloseCallback ioclose,
1820 void *ioctx, const char *encoding, int options)
1821{
1822 xmlSaveCtxtPtr ret;
1823
1824 ret = xmlNewSaveCtxt(encoding, options);
1825 if (ret == NULL) return(NULL);
1826 ret->buf = xmlOutputBufferCreateIO(iowrite, ioclose, ioctx, ret->handler);
1827 if (ret->buf == NULL) {
1828 xmlCharEncCloseFunc(ret->handler);
1829 xmlFreeSaveCtxt(ret);
1830 return(NULL);
1831 }
1832 return(ret);
1833}
1834
1846long
1847xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc)
1848{
1849 long ret = 0;
1850
1851 if ((ctxt == NULL) || (doc == NULL)) return(-1);
1852 if (xmlDocContentDumpOutput(ctxt, doc) < 0)
1853 return(-1);
1854 return(ret);
1855}
1856
1868long
1869xmlSaveTree(xmlSaveCtxtPtr ctxt, xmlNodePtr cur)
1870{
1871 long ret = 0;
1872
1873 if ((ctxt == NULL) || (cur == NULL)) return(-1);
1874#ifdef LIBXML_HTML_ENABLED
1875 if (ctxt->options & XML_SAVE_XHTML) {
1876 xhtmlNodeDumpOutput(ctxt, cur);
1877 return(ret);
1878 }
1879 if (((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
1880 (cur->doc->type == XML_HTML_DOCUMENT_NODE) &&
1881 ((ctxt->options & XML_SAVE_AS_XML) == 0)) ||
1882 (ctxt->options & XML_SAVE_AS_HTML)) {
1883 htmlNodeDumpOutputInternal(ctxt, cur);
1884 return(ret);
1885 }
1886#endif
1887 xmlNodeDumpOutputInternal(ctxt, cur);
1888 return(ret);
1889}
1890
1900int
1901xmlSaveFlush(xmlSaveCtxtPtr ctxt)
1902{
1903 if (ctxt == NULL) return(-1);
1904 if (ctxt->buf == NULL) return(-1);
1905 return(xmlOutputBufferFlush(ctxt->buf));
1906}
1907
1917int
1918xmlSaveClose(xmlSaveCtxtPtr ctxt)
1919{
1920 int ret;
1921
1922 if (ctxt == NULL) return(-1);
1923 ret = xmlSaveFlush(ctxt);
1924 xmlFreeSaveCtxt(ctxt);
1925 return(ret);
1926}
1927
1937int
1938xmlSaveSetEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape)
1939{
1940 if (ctxt == NULL) return(-1);
1941 ctxt->escape = escape;
1942 return(0);
1943}
1944
1954int
1955xmlSaveSetAttrEscape(xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape)
1956{
1957 if (ctxt == NULL) return(-1);
1958 ctxt->escapeAttr = escape;
1959 return(0);
1960}
1961
1962/************************************************************************
1963 * *
1964 * Public entry points based on buffers *
1965 * *
1966 ************************************************************************/
1967
1977void
1978xmlBufAttrSerializeTxtContent(xmlBufPtr buf, xmlDocPtr doc,
1979 xmlAttrPtr attr, const xmlChar * string)
1980{
1981 xmlChar *base, *cur;
1982
1983 if (string == NULL)
1984 return;
1985 base = cur = (xmlChar *) string;
1986 while (*cur != 0) {
1987 if (*cur == '\n') {
1988 if (base != cur)
1989 xmlBufAdd(buf, base, cur - base);
1990 xmlBufAdd(buf, BAD_CAST "&#10;", 5);
1991 cur++;
1992 base = cur;
1993 } else if (*cur == '\r') {
1994 if (base != cur)
1995 xmlBufAdd(buf, base, cur - base);
1996 xmlBufAdd(buf, BAD_CAST "&#13;", 5);
1997 cur++;
1998 base = cur;
1999 } else if (*cur == '\t') {
2000 if (base != cur)
2001 xmlBufAdd(buf, base, cur - base);
2002 xmlBufAdd(buf, BAD_CAST "&#9;", 4);
2003 cur++;
2004 base = cur;
2005 } else if (*cur == '"') {
2006 if (base != cur)
2007 xmlBufAdd(buf, base, cur - base);
2008 xmlBufAdd(buf, BAD_CAST "&quot;", 6);
2009 cur++;
2010 base = cur;
2011 } else if (*cur == '<') {
2012 if (base != cur)
2013 xmlBufAdd(buf, base, cur - base);
2014 xmlBufAdd(buf, BAD_CAST "&lt;", 4);
2015 cur++;
2016 base = cur;
2017 } else if (*cur == '>') {
2018 if (base != cur)
2019 xmlBufAdd(buf, base, cur - base);
2020 xmlBufAdd(buf, BAD_CAST "&gt;", 4);
2021 cur++;
2022 base = cur;
2023 } else if (*cur == '&') {
2024 if (base != cur)
2025 xmlBufAdd(buf, base, cur - base);
2026 xmlBufAdd(buf, BAD_CAST "&amp;", 5);
2027 cur++;
2028 base = cur;
2029 } else if ((*cur >= 0x80) && (cur[1] != 0) &&
2030 ((doc == NULL) || (doc->encoding == NULL))) {
2031 /*
2032 * We assume we have UTF-8 content.
2033 */
2034 unsigned char tmp[12];
2035 int val = 0, l = 1;
2036
2037 if (base != cur)
2038 xmlBufAdd(buf, base, cur - base);
2039 if (*cur < 0xC0) {
2040 xmlSaveErr(XML_SAVE_NOT_UTF8, (xmlNodePtr) attr, NULL);
2041 xmlSerializeHexCharRef(tmp, *cur);
2042 xmlBufAdd(buf, (xmlChar *) tmp, -1);
2043 cur++;
2044 base = cur;
2045 continue;
2046 } else if (*cur < 0xE0) {
2047 val = (cur[0]) & 0x1F;
2048 val <<= 6;
2049 val |= (cur[1]) & 0x3F;
2050 l = 2;
2051 } else if ((*cur < 0xF0) && (cur [2] != 0)) {
2052 val = (cur[0]) & 0x0F;
2053 val <<= 6;
2054 val |= (cur[1]) & 0x3F;
2055 val <<= 6;
2056 val |= (cur[2]) & 0x3F;
2057 l = 3;
2058 } else if ((*cur < 0xF8) && (cur [2] != 0) && (cur[3] != 0)) {
2059 val = (cur[0]) & 0x07;
2060 val <<= 6;
2061 val |= (cur[1]) & 0x3F;
2062 val <<= 6;
2063 val |= (cur[2]) & 0x3F;
2064 val <<= 6;
2065 val |= (cur[3]) & 0x3F;
2066 l = 4;
2067 }
2068 if ((l == 1) || (!IS_CHAR(val))) {
2069 xmlSaveErr(XML_SAVE_CHAR_INVALID, (xmlNodePtr) attr, NULL);
2070 xmlSerializeHexCharRef(tmp, *cur);
2071 xmlBufAdd(buf, (xmlChar *) tmp, -1);
2072 cur++;
2073 base = cur;
2074 continue;
2075 }
2076 /*
2077 * We could do multiple things here. Just save
2078 * as a char ref
2079 */
2080 xmlSerializeHexCharRef(tmp, val);
2081 xmlBufAdd(buf, (xmlChar *) tmp, -1);
2082 cur += l;
2083 base = cur;
2084 } else {
2085 cur++;
2086 }
2087 }
2088 if (base != cur)
2089 xmlBufAdd(buf, base, cur - base);
2090}
2091
2101void
2102xmlAttrSerializeTxtContent(xmlBufferPtr buf, xmlDocPtr doc,
2103 xmlAttrPtr attr, const xmlChar * string)
2104{
2105 xmlBufPtr buffer;
2106
2107 if ((buf == NULL) || (string == NULL))
2108 return;
2110 if (buffer == NULL)
2111 return;
2112 xmlBufAttrSerializeTxtContent(buffer, doc, attr, string);
2114}
2115
2132int
2133xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2134 int format)
2135{
2136 xmlBufPtr buffer;
2137 size_t ret;
2138
2139 if ((buf == NULL) || (cur == NULL))
2140 return(-1);
2142 if (buffer == NULL)
2143 return(-1);
2144 ret = xmlBufNodeDump(buffer, doc, cur, level, format);
2146 if (ret > INT_MAX)
2147 return(-1);
2148 return(ret);
2149}
2150
2167size_t
2168xmlBufNodeDump(xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
2169 int format)
2170{
2171 size_t use;
2172 int ret;
2173 xmlOutputBufferPtr outbuf;
2174 int oldalloc;
2175
2176 xmlInitParser();
2177
2178 if (cur == NULL) {
2179 return (-1);
2180 }
2181 if (buf == NULL) {
2182 return (-1);
2183 }
2184 outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
2185 if (outbuf == NULL) {
2186 xmlSaveErrMemory("creating buffer");
2187 return (-1);
2188 }
2189 memset(outbuf, 0, (size_t) sizeof(xmlOutputBuffer));
2190 outbuf->buffer = buf;
2191 outbuf->encoder = NULL;
2192 outbuf->writecallback = NULL;
2193 outbuf->closecallback = NULL;
2194 outbuf->context = NULL;
2195 outbuf->written = 0;
2196
2197 use = xmlBufUse(buf);
2198 oldalloc = xmlBufGetAllocationScheme(buf);
2199 xmlBufSetAllocationScheme(buf, XML_BUFFER_ALLOC_DOUBLEIT);
2200 xmlNodeDumpOutput(outbuf, doc, cur, level, format, NULL);
2201 xmlBufSetAllocationScheme(buf, oldalloc);
2202 xmlFree(outbuf);
2203 ret = xmlBufUse(buf) - use;
2204 return (ret);
2205}
2206
2215void
2216xmlElemDump(FILE * f, xmlDocPtr doc, xmlNodePtr cur)
2217{
2218 xmlOutputBufferPtr outbuf;
2219
2220 xmlInitParser();
2221
2222 if (cur == NULL) {
2223 return;
2224 }
2225
2226 outbuf = xmlOutputBufferCreateFile(f, NULL);
2227 if (outbuf == NULL)
2228 return;
2229 if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
2230#ifdef LIBXML_HTML_ENABLED
2231 htmlNodeDumpOutput(outbuf, doc, cur, NULL);
2232#else
2233 xmlSaveErr(XML_ERR_INTERNAL_ERROR, cur, "HTML support not compiled in\n");
2234#endif /* LIBXML_HTML_ENABLED */
2235 } else
2236 xmlNodeDumpOutput(outbuf, doc, cur, 0, 1, NULL);
2237 xmlOutputBufferClose(outbuf);
2238}
2239
2240/************************************************************************
2241 * *
2242 * Saving functions front-ends *
2243 * *
2244 ************************************************************************/
2245
2259void
2260xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
2261 int level, int format, const char *encoding)
2262{
2263 xmlSaveCtxt ctxt;
2264#ifdef LIBXML_HTML_ENABLED
2265 xmlDtdPtr dtd;
2266 int is_xhtml = 0;
2267#endif
2268
2269 (void) doc;
2270
2271 xmlInitParser();
2272
2273 if ((buf == NULL) || (cur == NULL)) return;
2274
2275 if (encoding == NULL)
2276 encoding = "UTF-8";
2277
2278 memset(&ctxt, 0, sizeof(ctxt));
2279 ctxt.buf = buf;
2280 ctxt.level = level;
2281 ctxt.format = format ? 1 : 0;
2282 ctxt.encoding = (const xmlChar *) encoding;
2283 xmlSaveCtxtInit(&ctxt);
2284 ctxt.options |= XML_SAVE_AS_XML;
2285
2286#ifdef LIBXML_HTML_ENABLED
2287 dtd = xmlGetIntSubset(doc);
2288 if (dtd != NULL) {
2289 is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
2290 if (is_xhtml < 0)
2291 is_xhtml = 0;
2292 }
2293
2294 if (is_xhtml)
2295 xhtmlNodeDumpOutput(&ctxt, cur);
2296 else
2297#endif
2298 xmlNodeDumpOutputInternal(&ctxt, cur);
2299}
2300
2316void
2317xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
2318 int * doc_txt_len, const char * txt_encoding,
2319 int format) {
2320 xmlSaveCtxt ctxt;
2321 int dummy = 0;
2322 xmlOutputBufferPtr out_buff = NULL;
2323 xmlCharEncodingHandlerPtr conv_hdlr = NULL;
2324
2325 if (doc_txt_len == NULL) {
2326 doc_txt_len = &dummy; /* Continue, caller just won't get length */
2327 }
2328
2329 if (doc_txt_ptr == NULL) {
2330 *doc_txt_len = 0;
2331 return;
2332 }
2333
2334 *doc_txt_ptr = NULL;
2335 *doc_txt_len = 0;
2336
2337 if (out_doc == NULL) {
2338 /* No document, no output */
2339 return;
2340 }
2341
2342 /*
2343 * Validate the encoding value, if provided.
2344 * This logic is copied from xmlSaveFileEnc.
2345 */
2346
2347 if (txt_encoding == NULL)
2348 txt_encoding = (const char *) out_doc->encoding;
2349 if (txt_encoding != NULL) {
2350 conv_hdlr = xmlFindCharEncodingHandler(txt_encoding);
2351 if ( conv_hdlr == NULL ) {
2352 xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, (xmlNodePtr) out_doc,
2353 txt_encoding);
2354 return;
2355 }
2356 }
2357
2358 if ((out_buff = xmlAllocOutputBuffer(conv_hdlr)) == NULL ) {
2359 xmlSaveErrMemory("creating buffer");
2360 xmlCharEncCloseFunc(conv_hdlr);
2361 return;
2362 }
2363
2364 memset(&ctxt, 0, sizeof(ctxt));
2365 ctxt.buf = out_buff;
2366 ctxt.level = 0;
2367 ctxt.format = format ? 1 : 0;
2368 ctxt.encoding = (const xmlChar *) txt_encoding;
2369 xmlSaveCtxtInit(&ctxt);
2370 ctxt.options |= XML_SAVE_AS_XML;
2371 xmlDocContentDumpOutput(&ctxt, out_doc);
2372 xmlOutputBufferFlush(out_buff);
2373 if (out_buff->conv != NULL) {
2374 *doc_txt_len = xmlBufUse(out_buff->conv);
2375 *doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->conv), *doc_txt_len);
2376 } else {
2377 *doc_txt_len = xmlBufUse(out_buff->buffer);
2378 *doc_txt_ptr = xmlStrndup(xmlBufContent(out_buff->buffer),*doc_txt_len);
2379 }
2380 (void)xmlOutputBufferClose(out_buff);
2381
2382 if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) {
2383 *doc_txt_len = 0;
2384 xmlSaveErrMemory("creating output");
2385 }
2386
2387 return;
2388}
2389
2401void
2402xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
2403 xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, 0);
2404}
2405
2419void
2420xmlDocDumpFormatMemory(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
2421 xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, format);
2422}
2423
2436void
2437xmlDocDumpMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
2438 int * doc_txt_len, const char * txt_encoding) {
2439 xmlDocDumpFormatMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len,
2440 txt_encoding, 0);
2441}
2442
2455int
2456xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) {
2457 xmlSaveCtxt ctxt;
2458 xmlOutputBufferPtr buf;
2459 const char * encoding;
2461 int ret;
2462
2463 if (cur == NULL) {
2464 return(-1);
2465 }
2466 encoding = (const char *) cur->encoding;
2467
2468 if (encoding != NULL) {
2470 if (handler == NULL) {
2471 xmlFree((char *) cur->encoding);
2472 cur->encoding = NULL;
2473 encoding = NULL;
2474 }
2475 }
2476 buf = xmlOutputBufferCreateFile(f, handler);
2477 if (buf == NULL) return(-1);
2478 memset(&ctxt, 0, sizeof(ctxt));
2479 ctxt.buf = buf;
2480 ctxt.level = 0;
2481 ctxt.format = format ? 1 : 0;
2482 ctxt.encoding = (const xmlChar *) encoding;
2483 xmlSaveCtxtInit(&ctxt);
2484 ctxt.options |= XML_SAVE_AS_XML;
2485 xmlDocContentDumpOutput(&ctxt, cur);
2486
2487 ret = xmlOutputBufferClose(buf);
2488 return(ret);
2489}
2490
2500int
2501xmlDocDump(FILE *f, xmlDocPtr cur) {
2502 return(xmlDocFormatDump (f, cur, 0));
2503}
2504
2517int
2518xmlSaveFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding) {
2519 xmlSaveCtxt ctxt;
2520 int ret;
2521
2522 if (buf == NULL) return(-1);
2523 if (cur == NULL) {
2524 xmlOutputBufferClose(buf);
2525 return(-1);
2526 }
2527 memset(&ctxt, 0, sizeof(ctxt));
2528 ctxt.buf = buf;
2529 ctxt.level = 0;
2530 ctxt.format = 0;
2531 ctxt.encoding = (const xmlChar *) encoding;
2532 xmlSaveCtxtInit(&ctxt);
2533 ctxt.options |= XML_SAVE_AS_XML;
2534 xmlDocContentDumpOutput(&ctxt, cur);
2535 ret = xmlOutputBufferClose(buf);
2536 return(ret);
2537}
2538
2552int
2553xmlSaveFormatFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur,
2554 const char *encoding, int format)
2555{
2556 xmlSaveCtxt ctxt;
2557 int ret;
2558
2559 if (buf == NULL) return(-1);
2560 if ((cur == NULL) ||
2561 ((cur->type != XML_DOCUMENT_NODE) &&
2562 (cur->type != XML_HTML_DOCUMENT_NODE))) {
2563 xmlOutputBufferClose(buf);
2564 return(-1);
2565 }
2566 memset(&ctxt, 0, sizeof(ctxt));
2567 ctxt.buf = buf;
2568 ctxt.level = 0;
2569 ctxt.format = format ? 1 : 0;
2570 ctxt.encoding = (const xmlChar *) encoding;
2571 xmlSaveCtxtInit(&ctxt);
2572 ctxt.options |= XML_SAVE_AS_XML;
2573 xmlDocContentDumpOutput(&ctxt, cur);
2574 ret = xmlOutputBufferClose(buf);
2575 return (ret);
2576}
2577
2591int
2592xmlSaveFormatFileEnc( const char * filename, xmlDocPtr cur,
2593 const char * encoding, int format ) {
2594 xmlSaveCtxt ctxt;
2595 xmlOutputBufferPtr buf;
2597 int ret;
2598
2599 if (cur == NULL)
2600 return(-1);
2601
2602 if (encoding == NULL)
2603 encoding = (const char *) cur->encoding;
2604
2605 if (encoding != NULL) {
2606
2608 if (handler == NULL)
2609 return(-1);
2610 }
2611
2612#ifdef LIBXML_ZLIB_ENABLED
2613 if (cur->compression < 0) cur->compression = xmlGetCompressMode();
2614#endif
2615 /*
2616 * save the content to a temp buffer.
2617 */
2618 buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
2619 if (buf == NULL) return(-1);
2620 memset(&ctxt, 0, sizeof(ctxt));
2621 ctxt.buf = buf;
2622 ctxt.level = 0;
2623 ctxt.format = format ? 1 : 0;
2624 ctxt.encoding = (const xmlChar *) encoding;
2625 xmlSaveCtxtInit(&ctxt);
2626 ctxt.options |= XML_SAVE_AS_XML;
2627
2628 xmlDocContentDumpOutput(&ctxt, cur);
2629
2630 ret = xmlOutputBufferClose(buf);
2631 return(ret);
2632}
2633
2634
2645int
2646xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) {
2647 return ( xmlSaveFormatFileEnc( filename, cur, encoding, 0 ) );
2648}
2649
2664int
2665xmlSaveFormatFile(const char *filename, xmlDocPtr cur, int format) {
2666 return ( xmlSaveFormatFileEnc( filename, cur, NULL, format ) );
2667}
2668
2679int
2680xmlSaveFile(const char *filename, xmlDocPtr cur) {
2681 return(xmlSaveFormatFileEnc(filename, cur, NULL, 0));
2682}
2683
2684#endif /* LIBXML_OUTPUT_ENABLED */
#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:902
int xmlBufGetAllocationScheme(xmlBufPtr buf)
Definition: buf.c:224
void xmlBufFree(xmlBufPtr buf)
Definition: buf.c:276
xmlBufPtr xmlBufCreate(void)
Definition: buf.c:122
int xmlBufMergeBuffer(xmlBufPtr buf, xmlBufferPtr buffer)
Definition: buf.c:993
xmlChar * xmlBufContent(const xmlBuf *buf)
Definition: buf.c:490
int xmlBufSetAllocationScheme(xmlBufPtr buf, xmlBufferAllocationScheme scheme)
Definition: buf.c:241
int xmlBufWriteQuotedString(xmlBufPtr buf, const xmlChar *string)
Definition: buf.c:852
xmlBufferPtr xmlBufBackToBuffer(xmlBufPtr buf)
Definition: buf.c:938
size_t xmlBufUse(const xmlBufPtr buf)
Definition: buf.c:570
int xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len)
Definition: buf.c:758
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:7512
#define INT_MAX
Definition: limits.h:26
return ret
Definition: mutex.c:146
r parent
Definition: btrfs.c:3010
XML_HIDDEN int xmlCharEncOutput(xmlOutputBufferPtr output, int init)
xmlCharEncodingHandlerPtr xmlFindCharEncodingHandler(const char *name)
Definition: encoding.c:1677
xmlCharEncoding xmlParseCharEncoding(const char *name)
Definition: encoding.c:1148
int(* xmlCharEncodingOutputFunc)(unsigned char *out, int *outlen, const unsigned char *in, int *inlen)
Definition: encoding.h:130
xmlCharEncoding
Definition: encoding.h:65
@ XML_CHAR_ENCODING_UTF8
Definition: encoding.h:68
@ XML_CHAR_ENCODING_NONE
Definition: encoding.h:67
@ XML_CHAR_ENCODING_ASCII
Definition: encoding.h:89
XMLPUBFUN int xmlCharEncCloseFunc(xmlCharEncodingHandler *handler)
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
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
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
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:71
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[]
void * xmlGenericErrorContext
Definition: globals.c:410
xmlFreeFunc xmlFree
Definition: globals.c:184
xmlGenericErrorFunc xmlGenericError
Definition: globals.c:396
xmlMallocFunc xmlMalloc
Definition: globals.c:193
XML_GLOBALS_PARSER XMLPUBFUN void xmlInitParser(void)
Definition: threads.c:569
XML_HIDDEN void XML_HIDDEN void __xmlSimpleError(int domain, int code, struct _xmlNode *node, const char *msg, const char *extra) LIBXML_ATTR_FORMAT(4
static int fd
Definition: io.c:51
#define memset(x, y, z)
Definition: compat.h:39
Definition: cookie.c:202
Definition: inflate.c:139
Definition: format.c:58
Definition: mem.c:349
Definition: name.c:39
Definition: dlist.c:348
static const WCHAR lang[]
Definition: wbemdisp.c:287
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
@ XML_FROM_OUTPUT
Definition: xmlerror.h:44
@ XML_SAVE_CHAR_INVALID
Definition: xmlerror.h:415
@ XML_ERR_INTERNAL_ERROR
Definition: xmlerror.h:101
@ XML_SAVE_NOT_UTF8
Definition: xmlerror.h:414
@ XML_SAVE_NO_DOCTYPE
Definition: xmlerror.h:416
@ XML_SAVE_UNKNOWN_ENCODING
Definition: xmlerror.h:417
@ XML_ERR_NO_MEMORY
Definition: xmlerror.h:102
#define MAX_INDENT
Definition: xmlsave.c:18
XMLPUBFUN xmlChar * xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:45
XMLPUBFUN int xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:428
XMLPUBFUN int xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:277
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:162
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN xmlChar * xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:69