diff options
Diffstat (limited to 'xmlsave.c')
| -rw-r--r-- | xmlsave.c | 112 |
1 files changed, 91 insertions, 21 deletions
@@ -122,19 +122,19 @@ xmlSaveErr(int code, xmlNodePtr node, const char *extra) switch(code) { case XML_SAVE_NOT_UTF8: - msg = "string is not in UTF-8"; + msg = "string is not in UTF-8\n"; break; case XML_SAVE_CHAR_INVALID: - msg = "invalid character value"; + msg = "invalid character value\n"; break; case XML_SAVE_UNKNOWN_ENCODING: - msg = "unknown encoding %s"; + msg = "unknown encoding %s\n"; break; case XML_SAVE_NO_DOCTYPE: - msg = "document has no DOCTYPE"; + msg = "document has no DOCTYPE\n"; break; default: - msg = "unexpected error number"; + msg = "unexpected error number\n"; } __xmlSimpleError(XML_FROM_OUTPUT, code, node, msg, extra); } @@ -392,7 +392,7 @@ xmlNewSaveCtxt(const char *encoding, int options) return(NULL); } ret->encoding = xmlStrdup((const xmlChar *)encoding); - ret->escape = xmlEscapeEntities; + ret->escape = NULL; } xmlSaveCtxtInit(ret); @@ -464,7 +464,7 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur); static void xmlNodeListDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur); static void xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur); void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur); -static void xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur); +static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur); /** * xmlNsDumpOutput: @@ -820,35 +820,77 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { * * Dump an XML document. */ -static void +static int xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) { #ifdef LIBXML_HTML_ENABLED xmlDtdPtr dtd; int is_xhtml = 0; #endif const xmlChar *oldenc = cur->encoding; + const xmlChar *oldctxtenc = ctxt->encoding; const xmlChar *encoding = ctxt->encoding; - xmlOutputBufferPtr buf; + xmlCharEncodingOutputFunc oldescape = ctxt->escape; + xmlCharEncodingOutputFunc oldescapeAttr = ctxt->escapeAttr; + xmlOutputBufferPtr buf = ctxt->buf; + xmlCharEncodingHandlerPtr handler = NULL; + xmlCharEncoding enc; xmlInitParser(); - if (ctxt->encoding != NULL) + if (ctxt->encoding != NULL) { cur->encoding = BAD_CAST ctxt->encoding; + } else if (cur->encoding != NULL) { + encoding = cur->encoding; + } else if (cur->charset != XML_CHAR_ENCODING_UTF8) { + encoding = (const xmlChar *) + xmlGetCharEncodingName((xmlCharEncoding) cur->charset); + } - buf = ctxt->buf; + 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); + 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); + } + 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 (ctxt->encoding == NULL) { - if (cur->encoding != NULL) - encoding = cur->encoding; - else if (cur->charset != XML_CHAR_ENCODING_UTF8) - encoding = (const xmlChar *) - xmlGetCharEncodingName((xmlCharEncoding) cur->charset); - } if (encoding != NULL) { xmlOutputBufferWrite(buf, 10, " encoding="); xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding); @@ -890,6 +932,25 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) { } 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; + } + ctxt->escape = oldescape; + ctxt->escapeAttr = oldescapeAttr; + } + return(0); } #ifdef LIBXML_HTML_ENABLED @@ -1316,6 +1377,11 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape); } +#if 0 + /* + * This was removed due to problems with HTML processors. + * See bug #345147. + */ /* * 4.8. Script and Style elements */ @@ -1380,7 +1446,10 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { } child = child->next; } - } else if (cur->children != NULL) { + } +#endif + + if (cur->children != NULL) { int indent = ctxt->format; if (format) xmlOutputBufferWrite(buf, 1, "\n"); @@ -1555,14 +1624,15 @@ xmlSaveDoc(xmlSaveCtxtPtr ctxt, xmlDocPtr doc) long ret = 0; if ((ctxt == NULL) || (doc == NULL)) return(-1); - xmlDocContentDumpOutput(ctxt, doc); + if (xmlDocContentDumpOutput(ctxt, doc) < 0) + return(-1); return(ret); } /** * xmlSaveTree: * @ctxt: a document saving context - * @node: a document + * @node: the top node of the subtree to save * * Save a subtree starting at the node parameter to a saving context * TODO: The function is not fully implemented yet as it does not return the |
