summaryrefslogtreecommitdiff
path: root/xmlsave.c
diff options
context:
space:
mode:
Diffstat (limited to 'xmlsave.c')
-rw-r--r--xmlsave.c279
1 files changed, 197 insertions, 82 deletions
diff --git a/xmlsave.c b/xmlsave.c
index 2a61577..a650722 100644
--- a/xmlsave.c
+++ b/xmlsave.c
@@ -457,6 +457,40 @@ xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr)
* *
************************************************************************/
+static int xmlSaveSwitchEncoding(xmlSaveCtxtPtr ctxt, const char *encoding) {
+ xmlOutputBufferPtr buf = ctxt->buf;
+
+ if ((encoding != NULL) && (buf->encoder == NULL) && (buf->conv == NULL)) {
+ buf->encoder = xmlFindCharEncodingHandler((const char *)encoding);
+ if (buf->encoder == NULL) {
+ xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL,
+ (const char *)encoding);
+ return(-1);
+ }
+ buf->conv = xmlBufferCreate();
+ if (buf->conv == NULL) {
+ xmlCharEncCloseFunc(buf->encoder);
+ xmlSaveErrMemory("creating encoding buffer");
+ return(-1);
+ }
+ /*
+ * initialize the state, e.g. if outputting a BOM
+ */
+ xmlCharEncOutFunc(buf->encoder, buf->conv, NULL);
+ }
+ return(0);
+}
+
+static int xmlSaveClearEncoding(xmlSaveCtxtPtr ctxt) {
+ xmlOutputBufferPtr buf = ctxt->buf;
+ xmlOutputBufferFlush(buf);
+ xmlCharEncCloseFunc(buf->encoder);
+ xmlBufferFree(buf->conv);
+ buf->encoder = NULL;
+ buf->conv = NULL;
+ return(0);
+}
+
#ifdef LIBXML_HTML_ENABLED
static void
xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur);
@@ -638,6 +672,66 @@ xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
}
}
+#ifdef LIBXML_HTML_ENABLED
+/**
+ * xmlNodeDumpOutputInternal:
+ * @cur: the current node
+ *
+ * Dump an HTML node, recursive behaviour, children are printed too.
+ */
+static int
+htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
+ const xmlChar *oldenc = NULL;
+ const xmlChar *oldctxtenc = ctxt->encoding;
+ const xmlChar *encoding = ctxt->encoding;
+ xmlOutputBufferPtr buf = ctxt->buf;
+ int switched_encoding = 0;
+ xmlDocPtr doc;
+
+ xmlInitParser();
+
+ doc = cur->doc; {
+ if (doc != NULL)
+ oldenc = doc->encoding;
+ if (ctxt->encoding != NULL) {
+ doc->encoding = BAD_CAST ctxt->encoding;
+ } else if (doc->encoding != NULL) {
+ encoding = doc->encoding;
+ }
+ }
+
+ if ((encoding != NULL) && (doc != NULL))
+ htmlSetMetaEncoding(doc, (const xmlChar *) encoding);
+ if ((encoding == NULL) && (doc != NULL))
+ encoding = htmlGetMetaEncoding(doc);
+ if (encoding == NULL)
+ encoding = BAD_CAST "HTML";
+ if ((encoding != NULL) && (oldctxtenc == NULL) &&
+ (buf->encoder == NULL) && (buf->conv == NULL)) {
+ if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
+ doc->encoding = oldenc;
+ return(-1);
+ }
+ switched_encoding = 1;
+ }
+ if (ctxt->options & XML_SAVE_FORMAT)
+ htmlNodeDumpFormatOutput(buf, doc, cur,
+ (const char *)encoding, 1);
+ else
+ htmlNodeDumpFormatOutput(buf, doc, cur,
+ (const char *)encoding, 0);
+ /*
+ * Restore the state of the saving context at the end of the document
+ */
+ if ((switched_encoding) && (oldctxtenc == NULL)) {
+ xmlSaveClearEncoding(ctxt);
+ }
+ if (doc != NULL)
+ doc->encoding = oldenc;
+ return(0);
+}
+#endif
+
/**
* xmlNodeDumpOutputInternal:
* @cur: the current node
@@ -662,6 +756,13 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
xmlDocContentDumpOutput(ctxt, (xmlDocPtr) cur);
return;
}
+#ifdef LIBXML_HTML_ENABLED
+ if ((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL) &&
+ (cur->doc->type == XML_HTML_DOCUMENT_NODE)) {
+ htmlNodeDumpOutputInternal(ctxt, cur);
+ return;
+ }
+#endif
if (cur->type == XML_DTD_NODE) {
xmlDtdDumpOutput(ctxt, (xmlDtdPtr) cur);
return;
@@ -835,9 +936,14 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
xmlCharEncodingOutputFunc oldescapeAttr = ctxt->escapeAttr;
xmlOutputBufferPtr buf = ctxt->buf;
xmlCharEncoding enc;
+ int switched_encoding = 0;
xmlInitParser();
+ if ((cur->type != XML_HTML_DOCUMENT_NODE) &&
+ (cur->type != XML_DOCUMENT_NODE))
+ return(-1);
+
if (ctxt->encoding != NULL) {
cur->encoding = BAD_CAST ctxt->encoding;
} else if (cur->encoding != NULL) {
@@ -847,110 +953,119 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
xmlGetCharEncodingName((xmlCharEncoding) cur->charset);
}
- enc = xmlParseCharEncoding((const char*) encoding);
- if ((encoding != NULL) && (oldctxtenc == NULL) &&
- (buf->encoder == NULL) && (buf->conv == NULL) &&
- ((ctxt->options & XML_SAVE_NO_DECL) == 0)) {
- if ((enc != XML_CHAR_ENCODING_UTF8) &&
- (enc != XML_CHAR_ENCODING_NONE) &&
- (enc != XML_CHAR_ENCODING_ASCII)) {
- /*
- * we need to switch to this encoding but just for this document
- * since we output the XMLDecl the conversion must be done to not
- * generate not well formed documents.
- */
- buf->encoder = xmlFindCharEncodingHandler((const char *)encoding);
- if (buf->encoder == NULL) {
- xmlSaveErr(XML_SAVE_UNKNOWN_ENCODING, NULL,
- (const char *)encoding);
+ if (cur->type == XML_HTML_DOCUMENT_NODE) {
+#ifdef LIBXML_HTML_ENABLED
+ if (encoding != NULL)
+ htmlSetMetaEncoding(cur, (const xmlChar *) encoding);
+ if (encoding == NULL)
+ encoding = htmlGetMetaEncoding(cur);
+ if (encoding == NULL)
+ encoding = BAD_CAST "HTML";
+ if ((encoding != NULL) && (oldctxtenc == NULL) &&
+ (buf->encoder == NULL) && (buf->conv == NULL)) {
+ if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
+ cur->encoding = oldenc;
return(-1);
}
- buf->conv = xmlBufferCreate();
- if (buf->conv == NULL) {
- xmlCharEncCloseFunc(buf->encoder);
- xmlSaveErrMemory("creating encoding buffer");
- return(-1);
+ switched_encoding = 1;
+ }
+ if (ctxt->options & XML_SAVE_FORMAT)
+ htmlDocContentDumpFormatOutput(buf, cur,
+ (const char *)encoding, 1);
+ else
+ htmlDocContentDumpFormatOutput(buf, cur,
+ (const char *)encoding, 0);
+ if (ctxt->encoding != NULL)
+ cur->encoding = oldenc;
+ return(0);
+#else
+ return(-1);
+#endif
+ } else if (cur->type == XML_DOCUMENT_NODE) {
+ enc = xmlParseCharEncoding((const char*) encoding);
+ if ((encoding != NULL) && (oldctxtenc == NULL) &&
+ (buf->encoder == NULL) && (buf->conv == NULL) &&
+ ((ctxt->options & XML_SAVE_NO_DECL) == 0)) {
+ if ((enc != XML_CHAR_ENCODING_UTF8) &&
+ (enc != XML_CHAR_ENCODING_NONE) &&
+ (enc != XML_CHAR_ENCODING_ASCII)) {
+ /*
+ * we need to switch to this encoding but just for this
+ * document since we output the XMLDecl the conversion
+ * must be done to not generate not well formed documents.
+ */
+ if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
+ cur->encoding = oldenc;
+ return(-1);
+ }
+ switched_encoding = 1;
}
- /*
- * initialize the state, e.g. if outputting a BOM
- */
- xmlCharEncOutFunc(buf->encoder, buf->conv, NULL);
+ if (ctxt->escape == xmlEscapeEntities)
+ ctxt->escape = NULL;
+ if (ctxt->escapeAttr == xmlEscapeEntities)
+ ctxt->escapeAttr = NULL;
}
- if (ctxt->escape == xmlEscapeEntities)
- ctxt->escape = NULL;
- if (ctxt->escapeAttr == xmlEscapeEntities)
- ctxt->escapeAttr = NULL;
- }
- /*
- * Save the XML declaration
- */
- if ((ctxt->options & XML_SAVE_NO_DECL) == 0) {
- xmlOutputBufferWrite(buf, 14, "<?xml version=");
- if (cur->version != NULL)
- xmlBufferWriteQuotedString(buf->buffer, cur->version);
- else
- xmlOutputBufferWrite(buf, 5, "\"1.0\"");
- if (encoding != NULL) {
- xmlOutputBufferWrite(buf, 10, " encoding=");
- xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
- }
- switch (cur->standalone) {
- case 0:
- xmlOutputBufferWrite(buf, 16, " standalone=\"no\"");
- break;
- case 1:
- xmlOutputBufferWrite(buf, 17, " standalone=\"yes\"");
- break;
+ /*
+ * Save the XML declaration
+ */
+ if ((ctxt->options & XML_SAVE_NO_DECL) == 0) {
+ xmlOutputBufferWrite(buf, 14, "<?xml version=");
+ if (cur->version != NULL)
+ xmlBufferWriteQuotedString(buf->buffer, cur->version);
+ else
+ xmlOutputBufferWrite(buf, 5, "\"1.0\"");
+ if (encoding != NULL) {
+ xmlOutputBufferWrite(buf, 10, " encoding=");
+ xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
+ }
+ switch (cur->standalone) {
+ case 0:
+ xmlOutputBufferWrite(buf, 16, " standalone=\"no\"");
+ break;
+ case 1:
+ xmlOutputBufferWrite(buf, 17, " standalone=\"yes\"");
+ break;
+ }
+ xmlOutputBufferWrite(buf, 3, "?>\n");
}
- xmlOutputBufferWrite(buf, 3, "?>\n");
- }
#ifdef LIBXML_HTML_ENABLED
- if ((ctxt->options & XML_SAVE_NO_XHTML) == 0) {
- dtd = xmlGetIntSubset(cur);
- if (dtd != NULL) {
- is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
- if (is_xhtml < 0) is_xhtml = 0;
+ if ((ctxt->options & XML_SAVE_NO_XHTML) == 0) {
+ dtd = xmlGetIntSubset(cur);
+ if (dtd != NULL) {
+ is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID);
+ if (is_xhtml < 0) is_xhtml = 0;
+ }
}
- }
#endif
- if (cur->children != NULL) {
- xmlNodePtr child = cur->children;
+ if (cur->children != NULL) {
+ xmlNodePtr child = cur->children;
- while (child != NULL) {
- ctxt->level = 0;
+ while (child != NULL) {
+ ctxt->level = 0;
#ifdef LIBXML_HTML_ENABLED
- if (is_xhtml)
- xhtmlNodeDumpOutput(ctxt, child);
- else
+ if (is_xhtml)
+ xhtmlNodeDumpOutput(ctxt, child);
+ else
#endif
- xmlNodeDumpOutputInternal(ctxt, child);
- xmlOutputBufferWrite(buf, 1, "\n");
- child = child->next;
+ xmlNodeDumpOutputInternal(ctxt, child);
+ xmlOutputBufferWrite(buf, 1, "\n");
+ child = child->next;
+ }
}
}
- if (ctxt->encoding != NULL)
- cur->encoding = oldenc;
-
+
/*
* Restore the state of the saving context at the end of the document
*/
- if ((encoding != NULL) && (oldctxtenc == NULL) &&
- ((ctxt->options & XML_SAVE_NO_DECL) == 0)) {
- if ((enc != XML_CHAR_ENCODING_UTF8) &&
- (enc != XML_CHAR_ENCODING_NONE) &&
- (enc != XML_CHAR_ENCODING_ASCII)) {
- xmlOutputBufferFlush(buf);
- xmlCharEncCloseFunc(buf->encoder);
- xmlBufferFree(buf->conv);
- buf->encoder = NULL;
- buf->conv = NULL;
- }
+ if ((switched_encoding) && (oldctxtenc == NULL)) {
+ xmlSaveClearEncoding(ctxt);
ctxt->escape = oldescape;
ctxt->escapeAttr = oldescapeAttr;
}
+ cur->encoding = oldenc;
return(0);
}