2 * xmlsave.c: Implemetation of the document serializer
4 * See Copyright for the status of this software.
13 #include <libxml/xmlmemory.h>
14 #include <libxml/parserInternals.h>
15 #include <libxml/tree.h>
16 #include <libxml/xmlsave.h>
20 #include <libxml/HTMLtree.h>
22 /************************************************************************
26 ************************************************************************/
27 #define XHTML_STRICT_PUBLIC_ID BAD_CAST \
28 "-//W3C//DTD XHTML 1.0 Strict//EN"
29 #define XHTML_STRICT_SYSTEM_ID BAD_CAST \
30 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
31 #define XHTML_FRAME_PUBLIC_ID BAD_CAST \
32 "-//W3C//DTD XHTML 1.0 Frameset//EN"
33 #define XHTML_FRAME_SYSTEM_ID BAD_CAST \
34 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"
35 #define XHTML_TRANS_PUBLIC_ID BAD_CAST \
36 "-//W3C//DTD XHTML 1.0 Transitional//EN"
37 #define XHTML_TRANS_SYSTEM_ID BAD_CAST \
38 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
40 #define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml"
43 * @systemID: the system identifier
44 * @publicID: the public identifier
46 * Try to find if the document correspond to an XHTML DTD
48 * Returns 1 if true, 0 if not and -1 in case of error
51 xmlIsXHTML(const xmlChar
*systemID
, const xmlChar
*publicID
) {
52 if ((systemID
== NULL
) && (publicID
== NULL
))
54 if (publicID
!= NULL
) {
55 if (xmlStrEqual(publicID
, XHTML_STRICT_PUBLIC_ID
)) return(1);
56 if (xmlStrEqual(publicID
, XHTML_FRAME_PUBLIC_ID
)) return(1);
57 if (xmlStrEqual(publicID
, XHTML_TRANS_PUBLIC_ID
)) return(1);
59 if (systemID
!= NULL
) {
60 if (xmlStrEqual(systemID
, XHTML_STRICT_SYSTEM_ID
)) return(1);
61 if (xmlStrEqual(systemID
, XHTML_FRAME_SYSTEM_ID
)) return(1);
62 if (xmlStrEqual(systemID
, XHTML_TRANS_SYSTEM_ID
)) return(1);
67 #ifdef LIBXML_OUTPUT_ENABLED
70 xmlGenericError(xmlGenericErrorContext, \
71 "Unimplemented block at %s:%d\n", \
78 const xmlChar
*filename
;
79 const xmlChar
*encoding
;
80 xmlCharEncodingHandlerPtr handler
;
81 xmlOutputBufferPtr buf
;
86 char indent
[MAX_INDENT
+ 1]; /* array for indenting output */
89 xmlCharEncodingOutputFunc escape
; /* used for element content */
90 xmlCharEncodingOutputFunc escapeAttr
;/* used for attribute content */
93 /************************************************************************
95 * Output error handlers *
97 ************************************************************************/
100 * @extra: extra informations
102 * Handle an out of memory condition
105 xmlSaveErrMemory(const char *extra
)
107 __xmlSimpleError(XML_FROM_OUTPUT
, XML_ERR_NO_MEMORY
, NULL
, NULL
, extra
);
112 * @code: the error number
113 * @node: the location of the error.
114 * @extra: extra informations
116 * Handle an out of memory condition
119 xmlSaveErr(int code
, xmlNodePtr node
, const char *extra
)
121 const char *msg
= NULL
;
124 case XML_SAVE_NOT_UTF8
:
125 msg
= "string is not in UTF-8\n";
127 case XML_SAVE_CHAR_INVALID
:
128 msg
= "invalid character value\n";
130 case XML_SAVE_UNKNOWN_ENCODING
:
131 msg
= "unknown encoding %s\n";
133 case XML_SAVE_NO_DOCTYPE
:
134 msg
= "document has no DOCTYPE\n";
137 msg
= "unexpected error number\n";
139 __xmlSimpleError(XML_FROM_OUTPUT
, code
, node
, msg
, extra
);
142 /************************************************************************
144 * Special escaping routines *
146 ************************************************************************/
147 static unsigned char *
148 xmlSerializeHexCharRef(unsigned char *out
, int val
) {
154 if (val
< 0x10) ptr
= out
;
155 else if (val
< 0x100) ptr
= out
+ 1;
156 else if (val
< 0x1000) ptr
= out
+ 2;
157 else if (val
< 0x10000) ptr
= out
+ 3;
158 else if (val
< 0x100000) ptr
= out
+ 4;
163 case 0: *ptr
-- = '0'; break;
164 case 1: *ptr
-- = '1'; break;
165 case 2: *ptr
-- = '2'; break;
166 case 3: *ptr
-- = '3'; break;
167 case 4: *ptr
-- = '4'; break;
168 case 5: *ptr
-- = '5'; break;
169 case 6: *ptr
-- = '6'; break;
170 case 7: *ptr
-- = '7'; break;
171 case 8: *ptr
-- = '8'; break;
172 case 9: *ptr
-- = '9'; break;
173 case 0xA: *ptr
-- = 'A'; break;
174 case 0xB: *ptr
-- = 'B'; break;
175 case 0xC: *ptr
-- = 'C'; break;
176 case 0xD: *ptr
-- = 'D'; break;
177 case 0xE: *ptr
-- = 'E'; break;
178 case 0xF: *ptr
-- = 'F'; break;
179 default: *ptr
-- = '0'; break;
190 * @out: a pointer to an array of bytes to store the result
191 * @outlen: the length of @out
192 * @in: a pointer to an array of unescaped UTF-8 bytes
193 * @inlen: the length of @in
195 * Take a block of UTF-8 chars in and escape them. Used when there is no
196 * encoding specified.
198 * Returns 0 if success, or -1 otherwise
199 * The value of @inlen after return is the number of octets consumed
200 * if the return value is positive, else unpredictable.
201 * The value of @outlen after return is the number of octets consumed.
204 xmlEscapeEntities(unsigned char* out
, int *outlen
,
205 const xmlChar
* in
, int *inlen
) {
206 unsigned char* outstart
= out
;
207 const unsigned char* base
= in
;
208 unsigned char* outend
= out
+ *outlen
;
209 const unsigned char* inend
;
212 inend
= in
+ (*inlen
);
214 while ((in
< inend
) && (out
< outend
)) {
216 if (outend
- out
< 4) break;
223 } else if (*in
== '>') {
224 if (outend
- out
< 4) break;
231 } else if (*in
== '&') {
232 if (outend
- out
< 5) break;
240 } else if (((*in
>= 0x20) && (*in
< 0x80)) ||
241 (*in
== '\n') || (*in
== '\t')) {
243 * default case, just copy !
247 } else if (*in
>= 0x80) {
249 * We assume we have UTF-8 input.
251 if (outend
- out
< 11) break;
254 xmlSaveErr(XML_SAVE_NOT_UTF8
, NULL
, NULL
);
257 } else if (*in
< 0xE0) {
258 if (inend
- in
< 2) break;
259 val
= (in
[0]) & 0x1F;
261 val
|= (in
[1]) & 0x3F;
263 } else if (*in
< 0xF0) {
264 if (inend
- in
< 3) break;
265 val
= (in
[0]) & 0x0F;
267 val
|= (in
[1]) & 0x3F;
269 val
|= (in
[2]) & 0x3F;
271 } else if (*in
< 0xF8) {
272 if (inend
- in
< 4) break;
273 val
= (in
[0]) & 0x07;
275 val
|= (in
[1]) & 0x3F;
277 val
|= (in
[2]) & 0x3F;
279 val
|= (in
[3]) & 0x3F;
282 xmlSaveErr(XML_SAVE_CHAR_INVALID
, NULL
, NULL
);
287 xmlSaveErr(XML_SAVE_CHAR_INVALID
, NULL
, NULL
);
293 * We could do multiple things here. Just save as a char ref
295 out
= xmlSerializeHexCharRef(out
, val
);
296 } else if (IS_BYTE_CHAR(*in
)) {
297 if (outend
- out
< 6) break;
298 out
= xmlSerializeHexCharRef(out
, *in
++);
300 xmlGenericError(xmlGenericErrorContext
,
301 "xmlEscapeEntities : char out of range\n");
306 *outlen
= out
- outstart
;
310 *outlen
= out
- outstart
;
315 /************************************************************************
317 * Allocation and deallocation *
319 ************************************************************************/
322 * @ctxt: the saving context
324 * Initialize a saving context
327 xmlSaveCtxtInit(xmlSaveCtxtPtr ctxt
)
332 if (ctxt
== NULL
) return;
333 if ((ctxt
->encoding
== NULL
) && (ctxt
->escape
== NULL
))
334 ctxt
->escape
= xmlEscapeEntities
;
335 len
= xmlStrlen((xmlChar
*)xmlTreeIndentString
);
336 if ((xmlTreeIndentString
== NULL
) || (len
== 0)) {
337 memset(&ctxt
->indent
[0], 0, MAX_INDENT
+ 1);
339 ctxt
->indent_size
= len
;
340 ctxt
->indent_nr
= MAX_INDENT
/ ctxt
->indent_size
;
341 for (i
= 0;i
< ctxt
->indent_nr
;i
++)
342 memcpy(&ctxt
->indent
[i
* ctxt
->indent_size
], xmlTreeIndentString
,
344 ctxt
->indent
[ctxt
->indent_nr
* ctxt
->indent_size
] = 0;
347 if (xmlSaveNoEmptyTags
) {
348 ctxt
->options
|= XML_SAVE_NO_EMPTY
;
355 * Free a saving context, destroying the ouptut in any remaining buffer
358 xmlFreeSaveCtxt(xmlSaveCtxtPtr ctxt
)
360 if (ctxt
== NULL
) return;
361 if (ctxt
->encoding
!= NULL
)
362 xmlFree((char *) ctxt
->encoding
);
363 if (ctxt
->buf
!= NULL
)
364 xmlOutputBufferClose(ctxt
->buf
);
371 * Create a new saving context
373 * Returns the new structure or NULL in case of error
375 static xmlSaveCtxtPtr
376 xmlNewSaveCtxt(const char *encoding
, int options
)
380 ret
= (xmlSaveCtxtPtr
) xmlMalloc(sizeof(xmlSaveCtxt
));
382 xmlSaveErrMemory("creating saving context");
385 memset(ret
, 0, sizeof(xmlSaveCtxt
));
387 if (encoding
!= NULL
) {
388 ret
->handler
= xmlFindCharEncodingHandler(encoding
);
389 if (ret
->handler
== NULL
) {
390 xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING
, NULL
, encoding
);
391 xmlFreeSaveCtxt(ret
);
394 ret
->encoding
= xmlStrdup((const xmlChar
*)encoding
);
397 xmlSaveCtxtInit(ret
);
403 /* Re-check this option as it may already have been set */
404 if ((ret
->options
& XML_SAVE_NO_EMPTY
) && ! (options
& XML_SAVE_NO_EMPTY
)) {
405 options
|= XML_SAVE_NO_EMPTY
;
408 ret
->options
= options
;
409 if (options
& XML_SAVE_FORMAT
)
415 /************************************************************************
417 * Dumping XML tree content to a simple buffer *
419 ************************************************************************/
421 * xmlAttrSerializeContent:
422 * @buf: the XML buffer output
424 * @attr: the attribute pointer
426 * Serialize the attribute in the buffer
429 xmlAttrSerializeContent(xmlOutputBufferPtr buf
, xmlAttrPtr attr
)
433 children
= attr
->children
;
434 while (children
!= NULL
) {
435 switch (children
->type
) {
437 xmlAttrSerializeTxtContent(buf
->buffer
, attr
->doc
,
438 attr
, children
->content
);
440 case XML_ENTITY_REF_NODE
:
441 xmlBufferAdd(buf
->buffer
, BAD_CAST
"&", 1);
442 xmlBufferAdd(buf
->buffer
, children
->name
,
443 xmlStrlen(children
->name
));
444 xmlBufferAdd(buf
->buffer
, BAD_CAST
";", 1);
447 /* should not happen unless we have a badly built tree */
450 children
= children
->next
;
454 /************************************************************************
456 * Dumping XML tree content to an I/O output buffer *
458 ************************************************************************/
460 static int xmlSaveSwitchEncoding(xmlSaveCtxtPtr ctxt
, const char *encoding
) {
461 xmlOutputBufferPtr buf
= ctxt
->buf
;
463 if ((encoding
!= NULL
) && (buf
->encoder
== NULL
) && (buf
->conv
== NULL
)) {
464 buf
->encoder
= xmlFindCharEncodingHandler((const char *)encoding
);
465 if (buf
->encoder
== NULL
) {
466 xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING
, NULL
,
467 (const char *)encoding
);
470 buf
->conv
= xmlBufferCreate();
471 if (buf
->conv
== NULL
) {
472 xmlCharEncCloseFunc(buf
->encoder
);
473 xmlSaveErrMemory("creating encoding buffer");
477 * initialize the state, e.g. if outputting a BOM
479 xmlCharEncOutFunc(buf
->encoder
, buf
->conv
, NULL
);
484 static int xmlSaveClearEncoding(xmlSaveCtxtPtr ctxt
) {
485 xmlOutputBufferPtr buf
= ctxt
->buf
;
486 xmlOutputBufferFlush(buf
);
487 xmlCharEncCloseFunc(buf
->encoder
);
488 xmlBufferFree(buf
->conv
);
494 #ifdef LIBXML_HTML_ENABLED
496 xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt
, xmlNodePtr cur
);
498 static void xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt
, xmlNodePtr cur
);
499 static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt
, xmlNodePtr cur
);
500 void xmlNsListDumpOutput(xmlOutputBufferPtr buf
, xmlNsPtr cur
);
501 static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt
, xmlDocPtr cur
);
505 * @buf: the XML buffer output
508 * Dump a local Namespace definition.
509 * Should be called in the context of attributes dumps.
512 xmlNsDumpOutput(xmlOutputBufferPtr buf
, xmlNsPtr cur
) {
513 if ((cur
== NULL
) || (buf
== NULL
)) return;
514 if ((cur
->type
== XML_LOCAL_NAMESPACE
) && (cur
->href
!= NULL
)) {
515 if (xmlStrEqual(cur
->prefix
, BAD_CAST
"xml"))
518 /* Within the context of an element attributes */
519 if (cur
->prefix
!= NULL
) {
520 xmlOutputBufferWrite(buf
, 7, " xmlns:");
521 xmlOutputBufferWriteString(buf
, (const char *)cur
->prefix
);
523 xmlOutputBufferWrite(buf
, 6, " xmlns");
524 xmlOutputBufferWrite(buf
, 1, "=");
525 xmlBufferWriteQuotedString(buf
->buffer
, cur
->href
);
530 * xmlNsListDumpOutput:
531 * @buf: the XML buffer output
532 * @cur: the first namespace
534 * Dump a list of local Namespace definitions.
535 * Should be called in the context of attributes dumps.
538 xmlNsListDumpOutput(xmlOutputBufferPtr buf
, xmlNsPtr cur
) {
539 while (cur
!= NULL
) {
540 xmlNsDumpOutput(buf
, cur
);
547 * @buf: the XML buffer output
548 * @dtd: the pointer to the DTD
550 * Dump the XML document DTD, if any.
553 xmlDtdDumpOutput(xmlSaveCtxtPtr ctxt
, xmlDtdPtr dtd
) {
554 xmlOutputBufferPtr buf
;
558 if (dtd
== NULL
) return;
559 if ((ctxt
== NULL
) || (ctxt
->buf
== NULL
))
562 xmlOutputBufferWrite(buf
, 10, "<!DOCTYPE ");
563 xmlOutputBufferWriteString(buf
, (const char *)dtd
->name
);
564 if (dtd
->ExternalID
!= NULL
) {
565 xmlOutputBufferWrite(buf
, 8, " PUBLIC ");
566 xmlBufferWriteQuotedString(buf
->buffer
, dtd
->ExternalID
);
567 xmlOutputBufferWrite(buf
, 1, " ");
568 xmlBufferWriteQuotedString(buf
->buffer
, dtd
->SystemID
);
569 } else if (dtd
->SystemID
!= NULL
) {
570 xmlOutputBufferWrite(buf
, 8, " SYSTEM ");
571 xmlBufferWriteQuotedString(buf
->buffer
, dtd
->SystemID
);
573 if ((dtd
->entities
== NULL
) && (dtd
->elements
== NULL
) &&
574 (dtd
->attributes
== NULL
) && (dtd
->notations
== NULL
) &&
575 (dtd
->pentities
== NULL
)) {
576 xmlOutputBufferWrite(buf
, 1, ">");
579 xmlOutputBufferWrite(buf
, 3, " [\n");
581 * Dump the notations first they are not in the DTD children list
582 * Do this only on a standalone DTD or on the internal subset though.
584 if ((dtd
->notations
!= NULL
) && ((dtd
->doc
== NULL
) ||
585 (dtd
->doc
->intSubset
== dtd
))) {
586 xmlDumpNotationTable(buf
->buffer
, (xmlNotationTablePtr
) dtd
->notations
);
588 format
= ctxt
->format
;
593 ctxt
->doc
= dtd
->doc
;
594 xmlNodeListDumpOutput(ctxt
, dtd
->children
);
595 ctxt
->format
= format
;
598 xmlOutputBufferWrite(buf
, 2, "]>");
603 * @buf: the XML buffer output
604 * @cur: the attribute pointer
606 * Dump an XML attribute
609 xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt
, xmlAttrPtr cur
) {
610 xmlOutputBufferPtr buf
;
612 if (cur
== NULL
) return;
614 if (buf
== NULL
) return;
615 xmlOutputBufferWrite(buf
, 1, " ");
616 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
617 xmlOutputBufferWriteString(buf
, (const char *)cur
->ns
->prefix
);
618 xmlOutputBufferWrite(buf
, 1, ":");
620 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
621 xmlOutputBufferWrite(buf
, 2, "=\"");
622 xmlAttrSerializeContent(buf
, cur
);
623 xmlOutputBufferWrite(buf
, 1, "\"");
627 * xmlAttrListDumpOutput:
628 * @buf: the XML buffer output
630 * @cur: the first attribute pointer
631 * @encoding: an optional encoding string
633 * Dump a list of XML attributes
636 xmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt
, xmlAttrPtr cur
) {
637 if (cur
== NULL
) return;
638 while (cur
!= NULL
) {
639 xmlAttrDumpOutput(ctxt
, cur
);
647 * xmlNodeListDumpOutput:
648 * @cur: the first node
650 * Dump an XML node list, recursive behaviour, children are printed too.
653 xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt
, xmlNodePtr cur
) {
654 xmlOutputBufferPtr buf
;
656 if (cur
== NULL
) return;
658 while (cur
!= NULL
) {
659 if ((ctxt
->format
) && (xmlIndentTreeOutput
) &&
660 ((cur
->type
== XML_ELEMENT_NODE
) ||
661 (cur
->type
== XML_COMMENT_NODE
) ||
662 (cur
->type
== XML_PI_NODE
)))
663 xmlOutputBufferWrite(buf
, ctxt
->indent_size
*
664 (ctxt
->level
> ctxt
->indent_nr
?
665 ctxt
->indent_nr
: ctxt
->level
),
667 xmlNodeDumpOutputInternal(ctxt
, cur
);
669 xmlOutputBufferWrite(buf
, 1, "\n");
675 #ifdef LIBXML_HTML_ENABLED
677 * xmlNodeDumpOutputInternal:
678 * @cur: the current node
680 * Dump an HTML node, recursive behaviour, children are printed too.
683 htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt
, xmlNodePtr cur
) {
684 const xmlChar
*oldenc
= NULL
;
685 const xmlChar
*oldctxtenc
= ctxt
->encoding
;
686 const xmlChar
*encoding
= ctxt
->encoding
;
687 xmlOutputBufferPtr buf
= ctxt
->buf
;
688 int switched_encoding
= 0;
695 oldenc
= doc
->encoding
;
696 if (ctxt
->encoding
!= NULL
) {
697 doc
->encoding
= BAD_CAST ctxt
->encoding
;
698 } else if (doc
->encoding
!= NULL
) {
699 encoding
= doc
->encoding
;
703 if ((encoding
!= NULL
) && (doc
!= NULL
))
704 htmlSetMetaEncoding(doc
, (const xmlChar
*) encoding
);
705 if ((encoding
== NULL
) && (doc
!= NULL
))
706 encoding
= htmlGetMetaEncoding(doc
);
707 if (encoding
== NULL
)
708 encoding
= BAD_CAST
"HTML";
709 if ((encoding
!= NULL
) && (oldctxtenc
== NULL
) &&
710 (buf
->encoder
== NULL
) && (buf
->conv
== NULL
)) {
711 if (xmlSaveSwitchEncoding(ctxt
, (const char*) encoding
) < 0) {
712 doc
->encoding
= oldenc
;
715 switched_encoding
= 1;
717 if (ctxt
->options
& XML_SAVE_FORMAT
)
718 htmlNodeDumpFormatOutput(buf
, doc
, cur
,
719 (const char *)encoding
, 1);
721 htmlNodeDumpFormatOutput(buf
, doc
, cur
,
722 (const char *)encoding
, 0);
724 * Restore the state of the saving context at the end of the document
726 if ((switched_encoding
) && (oldctxtenc
== NULL
)) {
727 xmlSaveClearEncoding(ctxt
);
730 doc
->encoding
= oldenc
;
736 * xmlNodeDumpOutputInternal:
737 * @cur: the current node
739 * Dump an XML node, recursive behaviour, children are printed too.
742 xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt
, xmlNodePtr cur
) {
745 xmlChar
*start
, *end
;
746 xmlOutputBufferPtr buf
;
748 if (cur
== NULL
) return;
750 if (cur
->type
== XML_XINCLUDE_START
)
752 if (cur
->type
== XML_XINCLUDE_END
)
754 if ((cur
->type
== XML_DOCUMENT_NODE
) ||
755 (cur
->type
== XML_HTML_DOCUMENT_NODE
)) {
756 xmlDocContentDumpOutput(ctxt
, (xmlDocPtr
) cur
);
759 #ifdef LIBXML_HTML_ENABLED
760 if (ctxt
->options
& XML_SAVE_XHTML
) {
761 xhtmlNodeDumpOutput(ctxt
, cur
);
764 if (((cur
->type
!= XML_NAMESPACE_DECL
) && (cur
->doc
!= NULL
) &&
765 (cur
->doc
->type
== XML_HTML_DOCUMENT_NODE
) &&
766 ((ctxt
->options
& XML_SAVE_AS_XML
) == 0)) ||
767 (ctxt
->options
& XML_SAVE_AS_HTML
)) {
768 htmlNodeDumpOutputInternal(ctxt
, cur
);
772 if (cur
->type
== XML_DTD_NODE
) {
773 xmlDtdDumpOutput(ctxt
, (xmlDtdPtr
) cur
);
776 if (cur
->type
== XML_DOCUMENT_FRAG_NODE
) {
777 xmlNodeListDumpOutput(ctxt
, cur
->children
);
780 if (cur
->type
== XML_ELEMENT_DECL
) {
781 xmlDumpElementDecl(buf
->buffer
, (xmlElementPtr
) cur
);
784 if (cur
->type
== XML_ATTRIBUTE_DECL
) {
785 xmlDumpAttributeDecl(buf
->buffer
, (xmlAttributePtr
) cur
);
788 if (cur
->type
== XML_ENTITY_DECL
) {
789 xmlDumpEntityDecl(buf
->buffer
, (xmlEntityPtr
) cur
);
792 if (cur
->type
== XML_TEXT_NODE
) {
793 if (cur
->content
!= NULL
) {
794 if (cur
->name
!= xmlStringTextNoenc
) {
795 xmlOutputBufferWriteEscape(buf
, cur
->content
, ctxt
->escape
);
798 * Disable escaping, needed for XSLT
800 xmlOutputBufferWriteString(buf
, (const char *) cur
->content
);
806 if (cur
->type
== XML_PI_NODE
) {
807 if (cur
->content
!= NULL
) {
808 xmlOutputBufferWrite(buf
, 2, "<?");
809 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
810 if (cur
->content
!= NULL
) {
811 xmlOutputBufferWrite(buf
, 1, " ");
812 xmlOutputBufferWriteString(buf
, (const char *)cur
->content
);
814 xmlOutputBufferWrite(buf
, 2, "?>");
816 xmlOutputBufferWrite(buf
, 2, "<?");
817 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
818 xmlOutputBufferWrite(buf
, 2, "?>");
822 if (cur
->type
== XML_COMMENT_NODE
) {
823 if (cur
->content
!= NULL
) {
824 xmlOutputBufferWrite(buf
, 4, "<!--");
825 xmlOutputBufferWriteString(buf
, (const char *)cur
->content
);
826 xmlOutputBufferWrite(buf
, 3, "-->");
830 if (cur
->type
== XML_ENTITY_REF_NODE
) {
831 xmlOutputBufferWrite(buf
, 1, "&");
832 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
833 xmlOutputBufferWrite(buf
, 1, ";");
836 if (cur
->type
== XML_CDATA_SECTION_NODE
) {
837 if (cur
->content
== NULL
|| *cur
->content
== '\0') {
838 xmlOutputBufferWrite(buf
, 12, "<![CDATA[]]>");
840 start
= end
= cur
->content
;
841 while (*end
!= '\0') {
842 if ((*end
== ']') && (*(end
+ 1) == ']') &&
843 (*(end
+ 2) == '>')) {
845 xmlOutputBufferWrite(buf
, 9, "<![CDATA[");
846 xmlOutputBufferWrite(buf
, end
- start
, (const char *)start
);
847 xmlOutputBufferWrite(buf
, 3, "]]>");
853 xmlOutputBufferWrite(buf
, 9, "<![CDATA[");
854 xmlOutputBufferWriteString(buf
, (const char *)start
);
855 xmlOutputBufferWrite(buf
, 3, "]]>");
860 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
861 xmlAttrDumpOutput(ctxt
, (xmlAttrPtr
) cur
);
864 if (cur
->type
== XML_NAMESPACE_DECL
) {
865 xmlNsDumpOutput(buf
, (xmlNsPtr
) cur
);
869 format
= ctxt
->format
;
872 while (tmp
!= NULL
) {
873 if ((tmp
->type
== XML_TEXT_NODE
) ||
874 (tmp
->type
== XML_CDATA_SECTION_NODE
) ||
875 (tmp
->type
== XML_ENTITY_REF_NODE
)) {
882 xmlOutputBufferWrite(buf
, 1, "<");
883 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
884 xmlOutputBufferWriteString(buf
, (const char *)cur
->ns
->prefix
);
885 xmlOutputBufferWrite(buf
, 1, ":");
888 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
890 xmlNsListDumpOutput(buf
, cur
->nsDef
);
891 if (cur
->properties
!= NULL
)
892 xmlAttrListDumpOutput(ctxt
, cur
->properties
);
894 if (((cur
->type
== XML_ELEMENT_NODE
) || (cur
->content
== NULL
)) &&
895 (cur
->children
== NULL
) && ((ctxt
->options
& XML_SAVE_NO_EMPTY
) == 0)) {
896 xmlOutputBufferWrite(buf
, 2, "/>");
897 ctxt
->format
= format
;
900 xmlOutputBufferWrite(buf
, 1, ">");
901 if ((cur
->type
!= XML_ELEMENT_NODE
) && (cur
->content
!= NULL
)) {
902 xmlOutputBufferWriteEscape(buf
, cur
->content
, ctxt
->escape
);
904 if (cur
->children
!= NULL
) {
905 if (ctxt
->format
) xmlOutputBufferWrite(buf
, 1, "\n");
906 if (ctxt
->level
>= 0) ctxt
->level
++;
907 xmlNodeListDumpOutput(ctxt
, cur
->children
);
908 if (ctxt
->level
> 0) ctxt
->level
--;
909 if ((xmlIndentTreeOutput
) && (ctxt
->format
))
910 xmlOutputBufferWrite(buf
, ctxt
->indent_size
*
911 (ctxt
->level
> ctxt
->indent_nr
?
912 ctxt
->indent_nr
: ctxt
->level
),
915 xmlOutputBufferWrite(buf
, 2, "</");
916 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
917 xmlOutputBufferWriteString(buf
, (const char *)cur
->ns
->prefix
);
918 xmlOutputBufferWrite(buf
, 1, ":");
921 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
922 xmlOutputBufferWrite(buf
, 1, ">");
923 ctxt
->format
= format
;
927 * xmlDocContentDumpOutput:
930 * Dump an XML document.
933 xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt
, xmlDocPtr cur
) {
934 #ifdef LIBXML_HTML_ENABLED
938 const xmlChar
*oldenc
= cur
->encoding
;
939 const xmlChar
*oldctxtenc
= ctxt
->encoding
;
940 const xmlChar
*encoding
= ctxt
->encoding
;
941 xmlCharEncodingOutputFunc oldescape
= ctxt
->escape
;
942 xmlCharEncodingOutputFunc oldescapeAttr
= ctxt
->escapeAttr
;
943 xmlOutputBufferPtr buf
= ctxt
->buf
;
945 int switched_encoding
= 0;
949 if ((cur
->type
!= XML_HTML_DOCUMENT_NODE
) &&
950 (cur
->type
!= XML_DOCUMENT_NODE
))
953 if (ctxt
->encoding
!= NULL
) {
954 cur
->encoding
= BAD_CAST ctxt
->encoding
;
955 } else if (cur
->encoding
!= NULL
) {
956 encoding
= cur
->encoding
;
957 } else if (cur
->charset
!= XML_CHAR_ENCODING_UTF8
) {
958 encoding
= (const xmlChar
*)
959 xmlGetCharEncodingName((xmlCharEncoding
) cur
->charset
);
962 if (((cur
->type
== XML_HTML_DOCUMENT_NODE
) &&
963 ((ctxt
->options
& XML_SAVE_AS_XML
) == 0) &&
964 ((ctxt
->options
& XML_SAVE_XHTML
) == 0)) ||
965 (ctxt
->options
& XML_SAVE_AS_HTML
)) {
966 #ifdef LIBXML_HTML_ENABLED
967 if (encoding
!= NULL
)
968 htmlSetMetaEncoding(cur
, (const xmlChar
*) encoding
);
969 if (encoding
== NULL
)
970 encoding
= htmlGetMetaEncoding(cur
);
971 if (encoding
== NULL
)
972 encoding
= BAD_CAST
"HTML";
973 if ((encoding
!= NULL
) && (oldctxtenc
== NULL
) &&
974 (buf
->encoder
== NULL
) && (buf
->conv
== NULL
)) {
975 if (xmlSaveSwitchEncoding(ctxt
, (const char*) encoding
) < 0) {
976 cur
->encoding
= oldenc
;
980 if (ctxt
->options
& XML_SAVE_FORMAT
)
981 htmlDocContentDumpFormatOutput(buf
, cur
,
982 (const char *)encoding
, 1);
984 htmlDocContentDumpFormatOutput(buf
, cur
,
985 (const char *)encoding
, 0);
986 if (ctxt
->encoding
!= NULL
)
987 cur
->encoding
= oldenc
;
992 } else if ((cur
->type
== XML_DOCUMENT_NODE
) ||
993 (ctxt
->options
& XML_SAVE_AS_XML
) ||
994 (ctxt
->options
& XML_SAVE_XHTML
)) {
995 enc
= xmlParseCharEncoding((const char*) encoding
);
996 if ((encoding
!= NULL
) && (oldctxtenc
== NULL
) &&
997 (buf
->encoder
== NULL
) && (buf
->conv
== NULL
) &&
998 ((ctxt
->options
& XML_SAVE_NO_DECL
) == 0)) {
999 if ((enc
!= XML_CHAR_ENCODING_UTF8
) &&
1000 (enc
!= XML_CHAR_ENCODING_NONE
) &&
1001 (enc
!= XML_CHAR_ENCODING_ASCII
)) {
1003 * we need to switch to this encoding but just for this
1004 * document since we output the XMLDecl the conversion
1005 * must be done to not generate not well formed documents.
1007 if (xmlSaveSwitchEncoding(ctxt
, (const char*) encoding
) < 0) {
1008 cur
->encoding
= oldenc
;
1011 switched_encoding
= 1;
1013 if (ctxt
->escape
== xmlEscapeEntities
)
1014 ctxt
->escape
= NULL
;
1015 if (ctxt
->escapeAttr
== xmlEscapeEntities
)
1016 ctxt
->escapeAttr
= NULL
;
1021 * Save the XML declaration
1023 if ((ctxt
->options
& XML_SAVE_NO_DECL
) == 0) {
1024 xmlOutputBufferWrite(buf
, 14, "<?xml version=");
1025 if (cur
->version
!= NULL
)
1026 xmlBufferWriteQuotedString(buf
->buffer
, cur
->version
);
1028 xmlOutputBufferWrite(buf
, 5, "\"1.0\"");
1029 if (encoding
!= NULL
) {
1030 xmlOutputBufferWrite(buf
, 10, " encoding=");
1031 xmlBufferWriteQuotedString(buf
->buffer
, (xmlChar
*) encoding
);
1033 switch (cur
->standalone
) {
1035 xmlOutputBufferWrite(buf
, 16, " standalone=\"no\"");
1038 xmlOutputBufferWrite(buf
, 17, " standalone=\"yes\"");
1041 xmlOutputBufferWrite(buf
, 3, "?>\n");
1044 #ifdef LIBXML_HTML_ENABLED
1045 if (ctxt
->options
& XML_SAVE_XHTML
)
1047 if ((ctxt
->options
& XML_SAVE_NO_XHTML
) == 0) {
1048 dtd
= xmlGetIntSubset(cur
);
1050 is_xhtml
= xmlIsXHTML(dtd
->SystemID
, dtd
->ExternalID
);
1051 if (is_xhtml
< 0) is_xhtml
= 0;
1055 if (cur
->children
!= NULL
) {
1056 xmlNodePtr child
= cur
->children
;
1058 while (child
!= NULL
) {
1060 #ifdef LIBXML_HTML_ENABLED
1062 xhtmlNodeDumpOutput(ctxt
, child
);
1065 xmlNodeDumpOutputInternal(ctxt
, child
);
1066 xmlOutputBufferWrite(buf
, 1, "\n");
1067 child
= child
->next
;
1073 * Restore the state of the saving context at the end of the document
1075 if ((switched_encoding
) && (oldctxtenc
== NULL
)) {
1076 xmlSaveClearEncoding(ctxt
);
1077 ctxt
->escape
= oldescape
;
1078 ctxt
->escapeAttr
= oldescapeAttr
;
1080 cur
->encoding
= oldenc
;
1084 #ifdef LIBXML_HTML_ENABLED
1085 /************************************************************************
1087 * Functions specific to XHTML serialization *
1089 ************************************************************************/
1095 * Check if a node is an empty xhtml node
1097 * Returns 1 if the node is an empty node, 0 if not and -1 in case of error
1100 xhtmlIsEmpty(xmlNodePtr node
) {
1103 if (node
->type
!= XML_ELEMENT_NODE
)
1105 if ((node
->ns
!= NULL
) && (!xmlStrEqual(node
->ns
->href
, XHTML_NS_NAME
)))
1107 if (node
->children
!= NULL
)
1109 switch (node
->name
[0]) {
1111 if (xmlStrEqual(node
->name
, BAD_CAST
"area"))
1115 if (xmlStrEqual(node
->name
, BAD_CAST
"br"))
1117 if (xmlStrEqual(node
->name
, BAD_CAST
"base"))
1119 if (xmlStrEqual(node
->name
, BAD_CAST
"basefont"))
1123 if (xmlStrEqual(node
->name
, BAD_CAST
"col"))
1127 if (xmlStrEqual(node
->name
, BAD_CAST
"frame"))
1131 if (xmlStrEqual(node
->name
, BAD_CAST
"hr"))
1135 if (xmlStrEqual(node
->name
, BAD_CAST
"img"))
1137 if (xmlStrEqual(node
->name
, BAD_CAST
"input"))
1139 if (xmlStrEqual(node
->name
, BAD_CAST
"isindex"))
1143 if (xmlStrEqual(node
->name
, BAD_CAST
"link"))
1147 if (xmlStrEqual(node
->name
, BAD_CAST
"meta"))
1151 if (xmlStrEqual(node
->name
, BAD_CAST
"param"))
1159 * xhtmlAttrListDumpOutput:
1160 * @cur: the first attribute pointer
1162 * Dump a list of XML attributes
1165 xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt
, xmlAttrPtr cur
) {
1166 xmlAttrPtr xml_lang
= NULL
;
1167 xmlAttrPtr lang
= NULL
;
1168 xmlAttrPtr name
= NULL
;
1169 xmlAttrPtr id
= NULL
;
1171 xmlOutputBufferPtr buf
;
1173 if (cur
== NULL
) return;
1175 parent
= cur
->parent
;
1176 while (cur
!= NULL
) {
1177 if ((cur
->ns
== NULL
) && (xmlStrEqual(cur
->name
, BAD_CAST
"id")))
1180 if ((cur
->ns
== NULL
) && (xmlStrEqual(cur
->name
, BAD_CAST
"name")))
1183 if ((cur
->ns
== NULL
) && (xmlStrEqual(cur
->name
, BAD_CAST
"lang")))
1186 if ((cur
->ns
!= NULL
) && (xmlStrEqual(cur
->name
, BAD_CAST
"lang")) &&
1187 (xmlStrEqual(cur
->ns
->prefix
, BAD_CAST
"xml")))
1189 else if ((cur
->ns
== NULL
) &&
1190 ((cur
->children
== NULL
) ||
1191 (cur
->children
->content
== NULL
) ||
1192 (cur
->children
->content
[0] == 0)) &&
1193 (htmlIsBooleanAttr(cur
->name
))) {
1194 if (cur
->children
!= NULL
)
1195 xmlFreeNode(cur
->children
);
1196 cur
->children
= xmlNewText(cur
->name
);
1197 if (cur
->children
!= NULL
)
1198 cur
->children
->parent
= (xmlNodePtr
) cur
;
1200 xmlAttrDumpOutput(ctxt
, cur
);
1206 if ((name
!= NULL
) && (id
== NULL
)) {
1207 if ((parent
!= NULL
) && (parent
->name
!= NULL
) &&
1208 ((xmlStrEqual(parent
->name
, BAD_CAST
"a")) ||
1209 (xmlStrEqual(parent
->name
, BAD_CAST
"p")) ||
1210 (xmlStrEqual(parent
->name
, BAD_CAST
"div")) ||
1211 (xmlStrEqual(parent
->name
, BAD_CAST
"img")) ||
1212 (xmlStrEqual(parent
->name
, BAD_CAST
"map")) ||
1213 (xmlStrEqual(parent
->name
, BAD_CAST
"applet")) ||
1214 (xmlStrEqual(parent
->name
, BAD_CAST
"form")) ||
1215 (xmlStrEqual(parent
->name
, BAD_CAST
"frame")) ||
1216 (xmlStrEqual(parent
->name
, BAD_CAST
"iframe")))) {
1217 xmlOutputBufferWrite(buf
, 5, " id=\"");
1218 xmlAttrSerializeContent(buf
, name
);
1219 xmlOutputBufferWrite(buf
, 1, "\"");
1225 if ((lang
!= NULL
) && (xml_lang
== NULL
)) {
1226 xmlOutputBufferWrite(buf
, 11, " xml:lang=\"");
1227 xmlAttrSerializeContent(buf
, lang
);
1228 xmlOutputBufferWrite(buf
, 1, "\"");
1230 if ((xml_lang
!= NULL
) && (lang
== NULL
)) {
1231 xmlOutputBufferWrite(buf
, 7, " lang=\"");
1232 xmlAttrSerializeContent(buf
, xml_lang
);
1233 xmlOutputBufferWrite(buf
, 1, "\"");
1238 * xhtmlNodeListDumpOutput:
1239 * @buf: the XML buffer output
1240 * @doc: the XHTML document
1241 * @cur: the first node
1242 * @level: the imbrication level for indenting
1243 * @format: is formatting allowed
1244 * @encoding: an optional encoding string
1246 * Dump an XML node list, recursive behaviour, children are printed too.
1247 * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
1248 * or xmlKeepBlanksDefault(0) was called
1251 xhtmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt
, xmlNodePtr cur
) {
1252 xmlOutputBufferPtr buf
;
1254 if (cur
== NULL
) return;
1256 while (cur
!= NULL
) {
1257 if ((ctxt
->format
) && (xmlIndentTreeOutput
) &&
1258 (cur
->type
== XML_ELEMENT_NODE
))
1259 xmlOutputBufferWrite(buf
, ctxt
->indent_size
*
1260 (ctxt
->level
> ctxt
->indent_nr
?
1261 ctxt
->indent_nr
: ctxt
->level
),
1263 xhtmlNodeDumpOutput(ctxt
, cur
);
1265 xmlOutputBufferWrite(buf
, 1, "\n");
1272 * xhtmlNodeDumpOutput:
1273 * @buf: the XML buffer output
1274 * @doc: the XHTML document
1275 * @cur: the current node
1276 * @level: the imbrication level for indenting
1277 * @format: is formatting allowed
1278 * @encoding: an optional encoding string
1280 * Dump an XHTML node, recursive behaviour, children are printed too.
1283 xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt
, xmlNodePtr cur
) {
1284 int format
, addmeta
= 0;
1286 xmlChar
*start
, *end
;
1287 xmlOutputBufferPtr buf
;
1289 if (cur
== NULL
) return;
1290 if ((cur
->type
== XML_DOCUMENT_NODE
) ||
1291 (cur
->type
== XML_HTML_DOCUMENT_NODE
)) {
1292 xmlDocContentDumpOutput(ctxt
, (xmlDocPtr
) cur
);
1295 if (cur
->type
== XML_XINCLUDE_START
)
1297 if (cur
->type
== XML_XINCLUDE_END
)
1299 if (cur
->type
== XML_DTD_NODE
) {
1300 xmlDtdDumpOutput(ctxt
, (xmlDtdPtr
) cur
);
1303 if (cur
->type
== XML_DOCUMENT_FRAG_NODE
) {
1304 xhtmlNodeListDumpOutput(ctxt
, cur
->children
);
1308 if (cur
->type
== XML_ELEMENT_DECL
) {
1309 xmlDumpElementDecl(buf
->buffer
, (xmlElementPtr
) cur
);
1312 if (cur
->type
== XML_ATTRIBUTE_DECL
) {
1313 xmlDumpAttributeDecl(buf
->buffer
, (xmlAttributePtr
) cur
);
1316 if (cur
->type
== XML_ENTITY_DECL
) {
1317 xmlDumpEntityDecl(buf
->buffer
, (xmlEntityPtr
) cur
);
1320 if (cur
->type
== XML_TEXT_NODE
) {
1321 if (cur
->content
!= NULL
) {
1322 if ((cur
->name
== xmlStringText
) ||
1323 (cur
->name
!= xmlStringTextNoenc
)) {
1324 xmlOutputBufferWriteEscape(buf
, cur
->content
, ctxt
->escape
);
1327 * Disable escaping, needed for XSLT
1329 xmlOutputBufferWriteString(buf
, (const char *) cur
->content
);
1335 if (cur
->type
== XML_PI_NODE
) {
1336 if (cur
->content
!= NULL
) {
1337 xmlOutputBufferWrite(buf
, 2, "<?");
1338 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
1339 if (cur
->content
!= NULL
) {
1340 xmlOutputBufferWrite(buf
, 1, " ");
1341 xmlOutputBufferWriteString(buf
, (const char *)cur
->content
);
1343 xmlOutputBufferWrite(buf
, 2, "?>");
1345 xmlOutputBufferWrite(buf
, 2, "<?");
1346 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
1347 xmlOutputBufferWrite(buf
, 2, "?>");
1351 if (cur
->type
== XML_COMMENT_NODE
) {
1352 if (cur
->content
!= NULL
) {
1353 xmlOutputBufferWrite(buf
, 4, "<!--");
1354 xmlOutputBufferWriteString(buf
, (const char *)cur
->content
);
1355 xmlOutputBufferWrite(buf
, 3, "-->");
1359 if (cur
->type
== XML_ENTITY_REF_NODE
) {
1360 xmlOutputBufferWrite(buf
, 1, "&");
1361 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
1362 xmlOutputBufferWrite(buf
, 1, ";");
1365 if (cur
->type
== XML_CDATA_SECTION_NODE
) {
1366 if (cur
->content
== NULL
|| *cur
->content
== '\0') {
1367 xmlOutputBufferWrite(buf
, 12, "<![CDATA[]]>");
1369 start
= end
= cur
->content
;
1370 while (*end
!= '\0') {
1371 if (*end
== ']' && *(end
+ 1) == ']' && *(end
+ 2) == '>') {
1373 xmlOutputBufferWrite(buf
, 9, "<![CDATA[");
1374 xmlOutputBufferWrite(buf
, end
- start
, (const char *)start
);
1375 xmlOutputBufferWrite(buf
, 3, "]]>");
1381 xmlOutputBufferWrite(buf
, 9, "<![CDATA[");
1382 xmlOutputBufferWriteString(buf
, (const char *)start
);
1383 xmlOutputBufferWrite(buf
, 3, "]]>");
1388 if (cur
->type
== XML_ATTRIBUTE_NODE
) {
1389 xmlAttrDumpOutput(ctxt
, (xmlAttrPtr
) cur
);
1393 format
= ctxt
->format
;
1395 tmp
= cur
->children
;
1396 while (tmp
!= NULL
) {
1397 if ((tmp
->type
== XML_TEXT_NODE
) ||
1398 (tmp
->type
== XML_ENTITY_REF_NODE
)) {
1405 xmlOutputBufferWrite(buf
, 1, "<");
1406 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
1407 xmlOutputBufferWriteString(buf
, (const char *)cur
->ns
->prefix
);
1408 xmlOutputBufferWrite(buf
, 1, ":");
1411 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
1413 xmlNsListDumpOutput(buf
, cur
->nsDef
);
1414 if ((xmlStrEqual(cur
->name
, BAD_CAST
"html") &&
1415 (cur
->ns
== NULL
) && (cur
->nsDef
== NULL
))) {
1417 * 3.1.1. Strictly Conforming Documents A.3.1.1 3/
1419 xmlOutputBufferWriteString(buf
,
1420 " xmlns=\"http://www.w3.org/1999/xhtml\"");
1422 if (cur
->properties
!= NULL
)
1423 xhtmlAttrListDumpOutput(ctxt
, cur
->properties
);
1425 if ((cur
->type
== XML_ELEMENT_NODE
) &&
1426 (cur
->parent
!= NULL
) &&
1427 (cur
->parent
->parent
== (xmlNodePtr
) cur
->doc
) &&
1428 xmlStrEqual(cur
->name
, BAD_CAST
"head") &&
1429 xmlStrEqual(cur
->parent
->name
, BAD_CAST
"html")) {
1431 tmp
= cur
->children
;
1432 while (tmp
!= NULL
) {
1433 if (xmlStrEqual(tmp
->name
, BAD_CAST
"meta")) {
1436 httpequiv
= xmlGetProp(tmp
, BAD_CAST
"http-equiv");
1437 if (httpequiv
!= NULL
) {
1438 if (xmlStrcasecmp(httpequiv
, BAD_CAST
"Content-Type") == 0) {
1451 if ((cur
->type
== XML_ELEMENT_NODE
) && (cur
->children
== NULL
)) {
1452 if (((cur
->ns
== NULL
) || (cur
->ns
->prefix
== NULL
)) &&
1453 ((xhtmlIsEmpty(cur
) == 1) && (addmeta
== 0))) {
1455 * C.2. Empty Elements
1457 xmlOutputBufferWrite(buf
, 3, " />");
1460 xmlOutputBufferWrite(buf
, 1, ">");
1462 xmlOutputBufferWrite(buf
, 1, "\n");
1463 if (xmlIndentTreeOutput
)
1464 xmlOutputBufferWrite(buf
, ctxt
->indent_size
*
1465 (ctxt
->level
+ 1 > ctxt
->indent_nr
?
1466 ctxt
->indent_nr
: ctxt
->level
+ 1), ctxt
->indent
);
1468 xmlOutputBufferWriteString(buf
,
1469 "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
1470 if (ctxt
->encoding
) {
1471 xmlOutputBufferWriteString(buf
, (const char *)ctxt
->encoding
);
1473 xmlOutputBufferWrite(buf
, 5, "UTF-8");
1475 xmlOutputBufferWrite(buf
, 4, "\" />");
1477 xmlOutputBufferWrite(buf
, 1, "\n");
1479 xmlOutputBufferWrite(buf
, 1, ">");
1482 * C.3. Element Minimization and Empty Element Content
1484 xmlOutputBufferWrite(buf
, 2, "</");
1485 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
1486 xmlOutputBufferWriteString(buf
, (const char *)cur
->ns
->prefix
);
1487 xmlOutputBufferWrite(buf
, 1, ":");
1489 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
1490 xmlOutputBufferWrite(buf
, 1, ">");
1494 xmlOutputBufferWrite(buf
, 1, ">");
1497 xmlOutputBufferWrite(buf
, 1, "\n");
1498 if (xmlIndentTreeOutput
)
1499 xmlOutputBufferWrite(buf
, ctxt
->indent_size
*
1500 (ctxt
->level
+ 1 > ctxt
->indent_nr
?
1501 ctxt
->indent_nr
: ctxt
->level
+ 1), ctxt
->indent
);
1503 xmlOutputBufferWriteString(buf
,
1504 "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=");
1505 if (ctxt
->encoding
) {
1506 xmlOutputBufferWriteString(buf
, (const char *)ctxt
->encoding
);
1508 xmlOutputBufferWrite(buf
, 5, "UTF-8");
1510 xmlOutputBufferWrite(buf
, 4, "\" />");
1512 if ((cur
->type
!= XML_ELEMENT_NODE
) && (cur
->content
!= NULL
)) {
1513 xmlOutputBufferWriteEscape(buf
, cur
->content
, ctxt
->escape
);
1518 * This was removed due to problems with HTML processors.
1522 * 4.8. Script and Style elements
1524 if ((cur
->type
== XML_ELEMENT_NODE
) &&
1525 ((xmlStrEqual(cur
->name
, BAD_CAST
"script")) ||
1526 (xmlStrEqual(cur
->name
, BAD_CAST
"style"))) &&
1527 ((cur
->ns
== NULL
) ||
1528 (xmlStrEqual(cur
->ns
->href
, XHTML_NS_NAME
)))) {
1529 xmlNodePtr child
= cur
->children
;
1531 while (child
!= NULL
) {
1532 if (child
->type
== XML_TEXT_NODE
) {
1533 if ((xmlStrchr(child
->content
, '<') == NULL
) &&
1534 (xmlStrchr(child
->content
, '&') == NULL
) &&
1535 (xmlStrstr(child
->content
, BAD_CAST
"]]>") == NULL
)) {
1536 /* Nothing to escape, so just output as is... */
1537 /* FIXME: Should we do something about "--" also? */
1538 int level
= ctxt
->level
;
1539 int indent
= ctxt
->format
;
1543 xmlOutputBufferWriteString(buf
, (const char *) child
->content
);
1544 /* (We cannot use xhtmlNodeDumpOutput() here because
1545 * we wish to leave '>' unescaped!) */
1546 ctxt
->level
= level
;
1547 ctxt
->format
= indent
;
1549 /* We must use a CDATA section. Unfortunately,
1550 * this will break CSS and JavaScript when read by
1551 * a browser in HTML4-compliant mode. :-( */
1552 start
= end
= child
->content
;
1553 while (*end
!= '\0') {
1555 *(end
+ 1) == ']' &&
1556 *(end
+ 2) == '>') {
1558 xmlOutputBufferWrite(buf
, 9, "<![CDATA[");
1559 xmlOutputBufferWrite(buf
, end
- start
,
1560 (const char *)start
);
1561 xmlOutputBufferWrite(buf
, 3, "]]>");
1567 xmlOutputBufferWrite(buf
, 9, "<![CDATA[");
1568 xmlOutputBufferWrite(buf
, end
- start
,
1569 (const char *)start
);
1570 xmlOutputBufferWrite(buf
, 3, "]]>");
1574 int level
= ctxt
->level
;
1575 int indent
= ctxt
->format
;
1579 xhtmlNodeDumpOutput(ctxt
, child
);
1580 ctxt
->level
= level
;
1581 ctxt
->format
= indent
;
1583 child
= child
->next
;
1588 if (cur
->children
!= NULL
) {
1589 int indent
= ctxt
->format
;
1591 if (format
) xmlOutputBufferWrite(buf
, 1, "\n");
1592 if (ctxt
->level
>= 0) ctxt
->level
++;
1593 ctxt
->format
= format
;
1594 xhtmlNodeListDumpOutput(ctxt
, cur
->children
);
1595 if (ctxt
->level
> 0) ctxt
->level
--;
1596 ctxt
->format
= indent
;
1597 if ((xmlIndentTreeOutput
) && (format
))
1598 xmlOutputBufferWrite(buf
, ctxt
->indent_size
*
1599 (ctxt
->level
> ctxt
->indent_nr
?
1600 ctxt
->indent_nr
: ctxt
->level
),
1603 xmlOutputBufferWrite(buf
, 2, "</");
1604 if ((cur
->ns
!= NULL
) && (cur
->ns
->prefix
!= NULL
)) {
1605 xmlOutputBufferWriteString(buf
, (const char *)cur
->ns
->prefix
);
1606 xmlOutputBufferWrite(buf
, 1, ":");
1609 xmlOutputBufferWriteString(buf
, (const char *)cur
->name
);
1610 xmlOutputBufferWrite(buf
, 1, ">");
1614 /************************************************************************
1616 * Public entry points *
1618 ************************************************************************/
1622 * @fd: a file descriptor number
1623 * @encoding: the encoding name to use or NULL
1624 * @options: a set of xmlSaveOptions
1626 * Create a document saving context serializing to a file descriptor
1627 * with the encoding and the options given.
1629 * Returns a new serialization context or NULL in case of error.
1632 xmlSaveToFd(int fd
, const char *encoding
, int options
)
1636 ret
= xmlNewSaveCtxt(encoding
, options
);
1637 if (ret
== NULL
) return(NULL
);
1638 ret
->buf
= xmlOutputBufferCreateFd(fd
, ret
->handler
);
1639 if (ret
->buf
== NULL
) {
1640 xmlFreeSaveCtxt(ret
);
1647 * xmlSaveToFilename:
1648 * @filename: a file name or an URL
1649 * @encoding: the encoding name to use or NULL
1650 * @options: a set of xmlSaveOptions
1652 * Create a document saving context serializing to a filename or possibly
1653 * to an URL (but this is less reliable) with the encoding and the options
1656 * Returns a new serialization context or NULL in case of error.
1659 xmlSaveToFilename(const char *filename
, const char *encoding
, int options
)
1662 int compression
= 0; /* TODO handle compression option */
1664 ret
= xmlNewSaveCtxt(encoding
, options
);
1665 if (ret
== NULL
) return(NULL
);
1666 ret
->buf
= xmlOutputBufferCreateFilename(filename
, ret
->handler
,
1668 if (ret
->buf
== NULL
) {
1669 xmlFreeSaveCtxt(ret
);
1678 * @encoding: the encoding name to use or NULL
1679 * @options: a set of xmlSaveOptions
1681 * Create a document saving context serializing to a buffer
1682 * with the encoding and the options given
1684 * Returns a new serialization context or NULL in case of error.
1688 xmlSaveToBuffer(xmlBufferPtr buffer
, const char *encoding
, int options
)
1691 xmlOutputBufferPtr out_buff
;
1692 xmlCharEncodingHandlerPtr handler
;
1694 ret
= xmlNewSaveCtxt(encoding
, options
);
1695 if (ret
== NULL
) return(NULL
);
1697 if (encoding
!= NULL
) {
1698 handler
= xmlFindCharEncodingHandler(encoding
);
1699 if (handler
== NULL
) {
1705 out_buff
= xmlOutputBufferCreateBuffer(buffer
, handler
);
1706 if (out_buff
== NULL
) {
1708 if (handler
) xmlCharEncCloseFunc(handler
);
1712 ret
->buf
= out_buff
;
1718 * @iowrite: an I/O write function
1719 * @ioclose: an I/O close function
1720 * @ioctx: an I/O handler
1721 * @encoding: the encoding name to use or NULL
1722 * @options: a set of xmlSaveOptions
1724 * Create a document saving context serializing to a file descriptor
1725 * with the encoding and the options given
1727 * Returns a new serialization context or NULL in case of error.
1730 xmlSaveToIO(xmlOutputWriteCallback iowrite
,
1731 xmlOutputCloseCallback ioclose
,
1732 void *ioctx
, const char *encoding
, int options
)
1736 ret
= xmlNewSaveCtxt(encoding
, options
);
1737 if (ret
== NULL
) return(NULL
);
1738 ret
->buf
= xmlOutputBufferCreateIO(iowrite
, ioclose
, ioctx
, ret
->handler
);
1739 if (ret
->buf
== NULL
) {
1740 xmlFreeSaveCtxt(ret
);
1748 * @ctxt: a document saving context
1751 * Save a full document to a saving context
1752 * TODO: The function is not fully implemented yet as it does not return the
1753 * byte count but 0 instead
1755 * Returns the number of byte written or -1 in case of error
1758 xmlSaveDoc(xmlSaveCtxtPtr ctxt
, xmlDocPtr doc
)
1762 if ((ctxt
== NULL
) || (doc
== NULL
)) return(-1);
1763 if (xmlDocContentDumpOutput(ctxt
, doc
) < 0)
1770 * @ctxt: a document saving context
1771 * @node: the top node of the subtree to save
1773 * Save a subtree starting at the node parameter to a saving context
1774 * TODO: The function is not fully implemented yet as it does not return the
1775 * byte count but 0 instead
1777 * Returns the number of byte written or -1 in case of error
1780 xmlSaveTree(xmlSaveCtxtPtr ctxt
, xmlNodePtr node
)
1784 if ((ctxt
== NULL
) || (node
== NULL
)) return(-1);
1785 xmlNodeDumpOutputInternal(ctxt
, node
);
1791 * @ctxt: a document saving context
1793 * Flush a document saving context, i.e. make sure that all bytes have
1796 * Returns the number of byte written or -1 in case of error.
1799 xmlSaveFlush(xmlSaveCtxtPtr ctxt
)
1801 if (ctxt
== NULL
) return(-1);
1802 if (ctxt
->buf
== NULL
) return(-1);
1803 return(xmlOutputBufferFlush(ctxt
->buf
));
1808 * @ctxt: a document saving context
1810 * Close a document saving context, i.e. make sure that all bytes have
1811 * been output and free the associated data.
1813 * Returns the number of byte written or -1 in case of error.
1816 xmlSaveClose(xmlSaveCtxtPtr ctxt
)
1820 if (ctxt
== NULL
) return(-1);
1821 ret
= xmlSaveFlush(ctxt
);
1822 xmlFreeSaveCtxt(ctxt
);
1828 * @ctxt: a document saving context
1829 * @escape: the escaping function
1831 * Set a custom escaping function to be used for text in element content
1833 * Returns 0 if successful or -1 in case of error.
1836 xmlSaveSetEscape(xmlSaveCtxtPtr ctxt
, xmlCharEncodingOutputFunc escape
)
1838 if (ctxt
== NULL
) return(-1);
1839 ctxt
->escape
= escape
;
1844 * xmlSaveSetAttrEscape:
1845 * @ctxt: a document saving context
1846 * @escape: the escaping function
1848 * Set a custom escaping function to be used for text in attribute content
1850 * Returns 0 if successful or -1 in case of error.
1853 xmlSaveSetAttrEscape(xmlSaveCtxtPtr ctxt
, xmlCharEncodingOutputFunc escape
)
1855 if (ctxt
== NULL
) return(-1);
1856 ctxt
->escapeAttr
= escape
;
1860 /************************************************************************
1862 * Public entry points based on buffers *
1864 ************************************************************************/
1866 * xmlAttrSerializeTxtContent:
1867 * @buf: the XML buffer output
1868 * @doc: the document
1869 * @attr: the attribute node
1870 * @string: the text content
1872 * Serialize text attribute values to an xml simple buffer
1875 xmlAttrSerializeTxtContent(xmlBufferPtr buf
, xmlDocPtr doc
,
1876 xmlAttrPtr attr
, const xmlChar
* string
)
1878 xmlChar
*base
, *cur
;
1882 base
= cur
= (xmlChar
*) string
;
1886 xmlBufferAdd(buf
, base
, cur
- base
);
1887 xmlBufferAdd(buf
, BAD_CAST
" ", 5);
1890 } else if (*cur
== '\r') {
1892 xmlBufferAdd(buf
, base
, cur
- base
);
1893 xmlBufferAdd(buf
, BAD_CAST
" ", 5);
1896 } else if (*cur
== '\t') {
1898 xmlBufferAdd(buf
, base
, cur
- base
);
1899 xmlBufferAdd(buf
, BAD_CAST
"	", 4);
1902 } else if (*cur
== '"') {
1904 xmlBufferAdd(buf
, base
, cur
- base
);
1905 xmlBufferAdd(buf
, BAD_CAST
""", 6);
1908 } else if (*cur
== '<') {
1910 xmlBufferAdd(buf
, base
, cur
- base
);
1911 xmlBufferAdd(buf
, BAD_CAST
"<", 4);
1914 } else if (*cur
== '>') {
1916 xmlBufferAdd(buf
, base
, cur
- base
);
1917 xmlBufferAdd(buf
, BAD_CAST
">", 4);
1920 } else if (*cur
== '&') {
1922 xmlBufferAdd(buf
, base
, cur
- base
);
1923 xmlBufferAdd(buf
, BAD_CAST
"&", 5);
1926 } else if ((*cur
>= 0x80) && ((doc
== NULL
) ||
1927 (doc
->encoding
== NULL
))) {
1929 * We assume we have UTF-8 content.
1931 unsigned char tmp
[12];
1935 xmlBufferAdd(buf
, base
, cur
- base
);
1937 xmlSaveErr(XML_SAVE_NOT_UTF8
, (xmlNodePtr
) attr
, NULL
);
1939 doc
->encoding
= xmlStrdup(BAD_CAST
"ISO-8859-1");
1940 xmlSerializeHexCharRef(tmp
, *cur
);
1941 xmlBufferAdd(buf
, (xmlChar
*) tmp
, -1);
1945 } else if (*cur
< 0xE0) {
1946 val
= (cur
[0]) & 0x1F;
1948 val
|= (cur
[1]) & 0x3F;
1950 } else if (*cur
< 0xF0) {
1951 val
= (cur
[0]) & 0x0F;
1953 val
|= (cur
[1]) & 0x3F;
1955 val
|= (cur
[2]) & 0x3F;
1957 } else if (*cur
< 0xF8) {
1958 val
= (cur
[0]) & 0x07;
1960 val
|= (cur
[1]) & 0x3F;
1962 val
|= (cur
[2]) & 0x3F;
1964 val
|= (cur
[3]) & 0x3F;
1967 if ((l
== 1) || (!IS_CHAR(val
))) {
1968 xmlSaveErr(XML_SAVE_CHAR_INVALID
, (xmlNodePtr
) attr
, NULL
);
1970 doc
->encoding
= xmlStrdup(BAD_CAST
"ISO-8859-1");
1972 xmlSerializeHexCharRef(tmp
, *cur
);
1973 xmlBufferAdd(buf
, (xmlChar
*) tmp
, -1);
1979 * We could do multiple things here. Just save
1982 xmlSerializeHexCharRef(tmp
, val
);
1983 xmlBufferAdd(buf
, (xmlChar
*) tmp
, -1);
1991 xmlBufferAdd(buf
, base
, cur
- base
);
1996 * @buf: the XML buffer output
1997 * @doc: the document
1998 * @cur: the current node
1999 * @level: the imbrication level for indenting
2000 * @format: is formatting allowed
2002 * Dump an XML node, recursive behaviour,children are printed too.
2003 * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2004 * or xmlKeepBlanksDefault(0) was called
2006 * Returns the number of bytes written to the buffer or -1 in case of error
2009 xmlNodeDump(xmlBufferPtr buf
, xmlDocPtr doc
, xmlNodePtr cur
, int level
,
2014 xmlOutputBufferPtr outbuf
;
2020 xmlGenericError(xmlGenericErrorContext
,
2021 "xmlNodeDump : node == NULL\n");
2027 xmlGenericError(xmlGenericErrorContext
,
2028 "xmlNodeDump : buf == NULL\n");
2032 outbuf
= (xmlOutputBufferPtr
) xmlMalloc(sizeof(xmlOutputBuffer
));
2033 if (outbuf
== NULL
) {
2034 xmlSaveErrMemory("creating buffer");
2037 memset(outbuf
, 0, (size_t) sizeof(xmlOutputBuffer
));
2038 outbuf
->buffer
= buf
;
2039 outbuf
->encoder
= NULL
;
2040 outbuf
->writecallback
= NULL
;
2041 outbuf
->closecallback
= NULL
;
2042 outbuf
->context
= NULL
;
2043 outbuf
->written
= 0;
2046 xmlNodeDumpOutput(outbuf
, doc
, cur
, level
, format
, NULL
);
2048 ret
= buf
->use
- use
;
2054 * @f: the FILE * for the output
2055 * @doc: the document
2056 * @cur: the current node
2058 * Dump an XML/HTML node, recursive behaviour, children are printed too.
2061 xmlElemDump(FILE * f
, xmlDocPtr doc
, xmlNodePtr cur
)
2063 xmlOutputBufferPtr outbuf
;
2069 xmlGenericError(xmlGenericErrorContext
,
2070 "xmlElemDump : cur == NULL\n");
2076 xmlGenericError(xmlGenericErrorContext
,
2077 "xmlElemDump : doc == NULL\n");
2081 outbuf
= xmlOutputBufferCreateFile(f
, NULL
);
2084 if ((doc
!= NULL
) && (doc
->type
== XML_HTML_DOCUMENT_NODE
)) {
2085 #ifdef LIBXML_HTML_ENABLED
2086 htmlNodeDumpOutput(outbuf
, doc
, cur
, NULL
);
2088 xmlSaveErr(XML_ERR_INTERNAL_ERROR
, cur
, "HTML support not compiled in\n");
2089 #endif /* LIBXML_HTML_ENABLED */
2091 xmlNodeDumpOutput(outbuf
, doc
, cur
, 0, 1, NULL
);
2092 xmlOutputBufferClose(outbuf
);
2095 /************************************************************************
2097 * Saving functions front-ends *
2099 ************************************************************************/
2102 * xmlNodeDumpOutput:
2103 * @buf: the XML buffer output
2104 * @doc: the document
2105 * @cur: the current node
2106 * @level: the imbrication level for indenting
2107 * @format: is formatting allowed
2108 * @encoding: an optional encoding string
2110 * Dump an XML node, recursive behaviour, children are printed too.
2111 * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2112 * or xmlKeepBlanksDefault(0) was called
2115 xmlNodeDumpOutput(xmlOutputBufferPtr buf
, xmlDocPtr doc
, xmlNodePtr cur
,
2116 int level
, int format
, const char *encoding
)
2119 #ifdef LIBXML_HTML_ENABLED
2126 if ((buf
== NULL
) || (cur
== NULL
)) return;
2128 if (encoding
== NULL
)
2131 memset(&ctxt
, 0, sizeof(ctxt
));
2135 ctxt
.format
= format
;
2136 ctxt
.encoding
= (const xmlChar
*) encoding
;
2137 xmlSaveCtxtInit(&ctxt
);
2138 ctxt
.options
|= XML_SAVE_AS_XML
;
2140 #ifdef LIBXML_HTML_ENABLED
2141 dtd
= xmlGetIntSubset(doc
);
2143 is_xhtml
= xmlIsXHTML(dtd
->SystemID
, dtd
->ExternalID
);
2149 xhtmlNodeDumpOutput(&ctxt
, cur
);
2152 xmlNodeDumpOutputInternal(&ctxt
, cur
);
2156 * xmlDocDumpFormatMemoryEnc:
2157 * @out_doc: Document to generate XML text from
2158 * @doc_txt_ptr: Memory pointer for allocated XML text
2159 * @doc_txt_len: Length of the generated XML text
2160 * @txt_encoding: Character encoding to use when generating XML text
2161 * @format: should formatting spaces been added
2163 * Dump the current DOM tree into memory using the character encoding specified
2164 * by the caller. Note it is up to the caller of this function to free the
2165 * allocated memory with xmlFree().
2166 * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2167 * or xmlKeepBlanksDefault(0) was called
2171 xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc
, xmlChar
**doc_txt_ptr
,
2172 int * doc_txt_len
, const char * txt_encoding
,
2176 xmlOutputBufferPtr out_buff
= NULL
;
2177 xmlCharEncodingHandlerPtr conv_hdlr
= NULL
;
2179 if (doc_txt_len
== NULL
) {
2180 doc_txt_len
= &dummy
; /* Continue, caller just won't get length */
2183 if (doc_txt_ptr
== NULL
) {
2188 *doc_txt_ptr
= NULL
;
2191 if (out_doc
== NULL
) {
2192 /* No document, no output */
2197 * Validate the encoding value, if provided.
2198 * This logic is copied from xmlSaveFileEnc.
2201 if (txt_encoding
== NULL
)
2202 txt_encoding
= (const char *) out_doc
->encoding
;
2203 if (txt_encoding
!= NULL
) {
2204 conv_hdlr
= xmlFindCharEncodingHandler(txt_encoding
);
2205 if ( conv_hdlr
== NULL
) {
2206 xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING
, (xmlNodePtr
) out_doc
,
2212 if ((out_buff
= xmlAllocOutputBuffer(conv_hdlr
)) == NULL
) {
2213 xmlSaveErrMemory("creating buffer");
2217 memset(&ctxt
, 0, sizeof(ctxt
));
2219 ctxt
.buf
= out_buff
;
2221 ctxt
.format
= format
;
2222 ctxt
.encoding
= (const xmlChar
*) txt_encoding
;
2223 xmlSaveCtxtInit(&ctxt
);
2224 ctxt
.options
|= XML_SAVE_AS_XML
;
2225 xmlDocContentDumpOutput(&ctxt
, out_doc
);
2226 xmlOutputBufferFlush(out_buff
);
2227 if (out_buff
->conv
!= NULL
) {
2228 *doc_txt_len
= out_buff
->conv
->use
;
2229 *doc_txt_ptr
= xmlStrndup(out_buff
->conv
->content
, *doc_txt_len
);
2231 *doc_txt_len
= out_buff
->buffer
->use
;
2232 *doc_txt_ptr
= xmlStrndup(out_buff
->buffer
->content
, *doc_txt_len
);
2234 (void)xmlOutputBufferClose(out_buff
);
2236 if ((*doc_txt_ptr
== NULL
) && (*doc_txt_len
> 0)) {
2238 xmlSaveErrMemory("creating output");
2246 * @cur: the document
2247 * @mem: OUT: the memory pointer
2248 * @size: OUT: the memory length
2250 * Dump an XML document in memory and return the #xmlChar * and it's size
2251 * in bytes. It's up to the caller to free the memory with xmlFree().
2252 * The resulting byte array is zero terminated, though the last 0 is not
2253 * included in the returned size.
2256 xmlDocDumpMemory(xmlDocPtr cur
, xmlChar
**mem
, int *size
) {
2257 xmlDocDumpFormatMemoryEnc(cur
, mem
, size
, NULL
, 0);
2261 * xmlDocDumpFormatMemory:
2262 * @cur: the document
2263 * @mem: OUT: the memory pointer
2264 * @size: OUT: the memory length
2265 * @format: should formatting spaces been added
2268 * Dump an XML document in memory and return the #xmlChar * and it's size.
2269 * It's up to the caller to free the memory with xmlFree().
2270 * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2271 * or xmlKeepBlanksDefault(0) was called
2274 xmlDocDumpFormatMemory(xmlDocPtr cur
, xmlChar
**mem
, int *size
, int format
) {
2275 xmlDocDumpFormatMemoryEnc(cur
, mem
, size
, NULL
, format
);
2279 * xmlDocDumpMemoryEnc:
2280 * @out_doc: Document to generate XML text from
2281 * @doc_txt_ptr: Memory pointer for allocated XML text
2282 * @doc_txt_len: Length of the generated XML text
2283 * @txt_encoding: Character encoding to use when generating XML text
2285 * Dump the current DOM tree into memory using the character encoding specified
2286 * by the caller. Note it is up to the caller of this function to free the
2287 * allocated memory with xmlFree().
2291 xmlDocDumpMemoryEnc(xmlDocPtr out_doc
, xmlChar
**doc_txt_ptr
,
2292 int * doc_txt_len
, const char * txt_encoding
) {
2293 xmlDocDumpFormatMemoryEnc(out_doc
, doc_txt_ptr
, doc_txt_len
,
2300 * @cur: the document
2301 * @format: should formatting spaces been added
2303 * Dump an XML document to an open FILE.
2305 * returns: the number of bytes written or -1 in case of failure.
2306 * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2307 * or xmlKeepBlanksDefault(0) was called
2310 xmlDocFormatDump(FILE *f
, xmlDocPtr cur
, int format
) {
2312 xmlOutputBufferPtr buf
;
2313 const char * encoding
;
2314 xmlCharEncodingHandlerPtr handler
= NULL
;
2319 xmlGenericError(xmlGenericErrorContext
,
2320 "xmlDocDump : document == NULL\n");
2324 encoding
= (const char *) cur
->encoding
;
2326 if (encoding
!= NULL
) {
2327 handler
= xmlFindCharEncodingHandler(encoding
);
2328 if (handler
== NULL
) {
2329 xmlFree((char *) cur
->encoding
);
2330 cur
->encoding
= NULL
;
2334 buf
= xmlOutputBufferCreateFile(f
, handler
);
2335 if (buf
== NULL
) return(-1);
2336 memset(&ctxt
, 0, sizeof(ctxt
));
2340 ctxt
.format
= format
;
2341 ctxt
.encoding
= (const xmlChar
*) encoding
;
2342 xmlSaveCtxtInit(&ctxt
);
2343 ctxt
.options
|= XML_SAVE_AS_XML
;
2344 xmlDocContentDumpOutput(&ctxt
, cur
);
2346 ret
= xmlOutputBufferClose(buf
);
2353 * @cur: the document
2355 * Dump an XML document to an open FILE.
2357 * returns: the number of bytes written or -1 in case of failure.
2360 xmlDocDump(FILE *f
, xmlDocPtr cur
) {
2361 return(xmlDocFormatDump (f
, cur
, 0));
2366 * @buf: an output I/O buffer
2367 * @cur: the document
2368 * @encoding: the encoding if any assuming the I/O layer handles the trancoding
2370 * Dump an XML document to an I/O buffer.
2371 * Warning ! This call xmlOutputBufferClose() on buf which is not available
2374 * returns: the number of bytes written or -1 in case of failure.
2377 xmlSaveFileTo(xmlOutputBufferPtr buf
, xmlDocPtr cur
, const char *encoding
) {
2381 if (buf
== NULL
) return(-1);
2383 xmlOutputBufferClose(buf
);
2386 memset(&ctxt
, 0, sizeof(ctxt
));
2391 ctxt
.encoding
= (const xmlChar
*) encoding
;
2392 xmlSaveCtxtInit(&ctxt
);
2393 ctxt
.options
|= XML_SAVE_AS_XML
;
2394 xmlDocContentDumpOutput(&ctxt
, cur
);
2395 ret
= xmlOutputBufferClose(buf
);
2400 * xmlSaveFormatFileTo:
2401 * @buf: an output I/O buffer
2402 * @cur: the document
2403 * @encoding: the encoding if any assuming the I/O layer handles the trancoding
2404 * @format: should formatting spaces been added
2406 * Dump an XML document to an I/O buffer.
2407 * Warning ! This call xmlOutputBufferClose() on buf which is not available
2410 * returns: the number of bytes written or -1 in case of failure.
2413 xmlSaveFormatFileTo(xmlOutputBufferPtr buf
, xmlDocPtr cur
,
2414 const char *encoding
, int format
)
2419 if (buf
== NULL
) return(-1);
2420 if ((cur
== NULL
) ||
2421 ((cur
->type
!= XML_DOCUMENT_NODE
) &&
2422 (cur
->type
!= XML_HTML_DOCUMENT_NODE
))) {
2423 xmlOutputBufferClose(buf
);
2426 memset(&ctxt
, 0, sizeof(ctxt
));
2430 ctxt
.format
= format
;
2431 ctxt
.encoding
= (const xmlChar
*) encoding
;
2432 xmlSaveCtxtInit(&ctxt
);
2433 ctxt
.options
|= XML_SAVE_AS_XML
;
2434 xmlDocContentDumpOutput(&ctxt
, cur
);
2435 ret
= xmlOutputBufferClose(buf
);
2440 * xmlSaveFormatFileEnc:
2441 * @filename: the filename or URL to output
2442 * @cur: the document being saved
2443 * @encoding: the name of the encoding to use or NULL.
2444 * @format: should formatting spaces be added.
2446 * Dump an XML document to a file or an URL.
2448 * Returns the number of bytes written or -1 in case of error.
2449 * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2450 * or xmlKeepBlanksDefault(0) was called
2453 xmlSaveFormatFileEnc( const char * filename
, xmlDocPtr cur
,
2454 const char * encoding
, int format
) {
2456 xmlOutputBufferPtr buf
;
2457 xmlCharEncodingHandlerPtr handler
= NULL
;
2463 if (encoding
== NULL
)
2464 encoding
= (const char *) cur
->encoding
;
2466 if (encoding
!= NULL
) {
2468 handler
= xmlFindCharEncodingHandler(encoding
);
2469 if (handler
== NULL
)
2474 if (cur
->compression
< 0) cur
->compression
= xmlGetCompressMode();
2477 * save the content to a temp buffer.
2479 buf
= xmlOutputBufferCreateFilename(filename
, handler
, cur
->compression
);
2480 if (buf
== NULL
) return(-1);
2481 memset(&ctxt
, 0, sizeof(ctxt
));
2485 ctxt
.format
= format
;
2486 ctxt
.encoding
= (const xmlChar
*) encoding
;
2487 xmlSaveCtxtInit(&ctxt
);
2488 ctxt
.options
|= XML_SAVE_AS_XML
;
2490 xmlDocContentDumpOutput(&ctxt
, cur
);
2492 ret
= xmlOutputBufferClose(buf
);
2499 * @filename: the filename (or URL)
2500 * @cur: the document
2501 * @encoding: the name of an encoding (or NULL)
2503 * Dump an XML document, converting it to the given encoding
2505 * returns: the number of bytes written or -1 in case of failure.
2508 xmlSaveFileEnc(const char *filename
, xmlDocPtr cur
, const char *encoding
) {
2509 return ( xmlSaveFormatFileEnc( filename
, cur
, encoding
, 0 ) );
2513 * xmlSaveFormatFile:
2514 * @filename: the filename (or URL)
2515 * @cur: the document
2516 * @format: should formatting spaces been added
2518 * Dump an XML document to a file. Will use compression if
2519 * compiled in and enabled. If @filename is "-" the stdout file is
2520 * used. If @format is set then the document will be indented on output.
2521 * Note that @format = 1 provide node indenting only if xmlIndentTreeOutput = 1
2522 * or xmlKeepBlanksDefault(0) was called
2524 * returns: the number of bytes written or -1 in case of failure.
2527 xmlSaveFormatFile(const char *filename
, xmlDocPtr cur
, int format
) {
2528 return ( xmlSaveFormatFileEnc( filename
, cur
, NULL
, format
) );
2533 * @filename: the filename (or URL)
2534 * @cur: the document
2536 * Dump an XML document to a file. Will use compression if
2537 * compiled in and enabled. If @filename is "-" the stdout file is
2539 * returns: the number of bytes written or -1 in case of failure.
2542 xmlSaveFile(const char *filename
, xmlDocPtr cur
) {
2543 return(xmlSaveFormatFileEnc(filename
, cur
, NULL
, 0));
2546 #endif /* LIBXML_OUTPUT_ENABLED */
2548 #define bottom_xmlsave
2549 #include "elfgcchack.h"