diff options
Diffstat (limited to 'xmlsave.c')
-rw-r--r-- | xmlsave.c | 279 |
1 files changed, 197 insertions, 82 deletions
@@ -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); } |