--- parser3/src/classes/xdoc.C 2004/02/17 15:08:14 1.136 +++ parser3/src/classes/xdoc.C 2004/02/18 12:46:49 1.140 @@ -9,7 +9,7 @@ #ifdef XML -static const char * const IDENT_XDOC_C="$Date: 2004/02/17 15:08:14 $"; +static const char * const IDENT_XDOC_C="$Date: 2004/02/18 12:46:49 $"; #include "gdome.h" #include "libxml/tree.h" @@ -595,59 +595,71 @@ static void prepare_output_options(Reque } } -/// patching piece from libxslt not to set meta encoding -static void -pa_xsltSaveResultToMem( - xmlChar*& doc_txt_ptr, int& doc_txt_len, - xmlDocPtr result, - xsltStylesheetPtr style, - xmlCharEncodingHandler* encoder) -{ +/// patching piecees from libxslt and libxml not to set meta encoding +static int +pa_xsltSaveResultTo(xmlOutputBufferPtr buf, xmlDocPtr result, + xsltStylesheetPtr style, + const xmlChar *header_encoding) { const xmlChar *encoding; int base; const xmlChar *method; int indent; - xmlOutputBufferPtr buf = 0; - if ((result == NULL) || (style == NULL)) - return; + if ((buf == NULL) || (result == NULL) || (style == NULL)) + return(-1); if ((result->children == NULL) || ((result->children->type == XML_DTD_NODE) && (result->children->next == NULL))) - return; + return(0); if ((style->methodURI != NULL) && ((style->method == NULL) || (!xmlStrEqual(style->method, (const xmlChar *) "xhtml")))) { xsltGenericError(xsltGenericErrorContext, "xsltSaveResultTo : unknown ouput method\n"); - return; + return(-1); } + base = buf->written; + XSLT_GET_IMPORT_PTR(method, style, method) XSLT_GET_IMPORT_PTR(encoding, style, encoding) + if(header_encoding) + encoding=header_encoding; XSLT_GET_IMPORT_INT(indent, style, indent); if ((method == NULL) && (result->type == XML_HTML_DOCUMENT_NODE)) - method = (const xmlChar *) "html"; + method = BAD_CAST "html"; + + int omitXmlDecl; + XSLT_GET_IMPORT_INT(omitXmlDecl, style, omitXmlDeclaration); if ((method != NULL) && - (xmlStrEqual(method, (const xmlChar *) "html") - ||xmlStrEqual(method, (const xmlChar *) "xhtml"))) { + (xmlStrEqual(method, (const xmlChar *) "html"))) { if (indent == -1) indent = 1; - // - // * xmlDocDumpFormatMemoryEnc: - // Note it is up to the caller of this function to free the - // allocated memory with xmlFree() - // - // we wont free anything, and wont copy that data anymore [already done inside and zeroterminated] - xmlDocDumpFormatMemoryEnc(result, &doc_txt_ptr, &doc_txt_len, (const char *) encoding, + + int is_xhtml = 0; + xmlDtdPtr dtd = xmlGetIntSubset(result); + if (dtd != NULL) { + is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID); + if (is_xhtml < 0) + is_xhtml = 0; + } + if(is_xhtml) { + method = BAD_CAST "xml"; + omitXmlDecl = 0; + } else { + htmlDocContentDumpFormatOutput(buf, result, (const char *) encoding, indent); - } else if ((method != NULL) && + xmlOutputBufferFlush(buf); + goto finish; + } + } + + if ((method != NULL) && (xmlStrEqual(method, (const xmlChar *) "text"))) { xmlNodePtr cur; - buf = xmlAllocOutputBuffer(encoder); cur = result->children; while (cur != NULL) { @@ -684,27 +696,23 @@ pa_xsltSaveResultToMem( } } while (cur != NULL); } + xmlOutputBufferFlush(buf); } else { - int omitXmlDecl; int standalone; - buf = xmlAllocOutputBuffer(encoder); - XSLT_GET_IMPORT_INT(omitXmlDecl, style, omitXmlDeclaration); XSLT_GET_IMPORT_INT(standalone, style, standalone); if (omitXmlDecl != 1) { xmlOutputBufferWriteString(buf, "version != NULL) - xmlBufferWriteQuotedString(buf->buffer, result->version); - else - xmlOutputBufferWriteString(buf, "\"1.0\""); + xmlBufferWriteQuotedString(buf->buffer, result->version); + else + xmlOutputBufferWriteString(buf, "\"1.0\""); if (encoding == NULL) { if (result->encoding != NULL) encoding = result->encoding; else if (result->charset != XML_CHAR_ENCODING_UTF8) - encoding = (const xmlChar *) - xmlGetCharEncodingName((xmlCharEncoding) - result->charset); + encoding = BAD_CAST xmlGetCharEncodingName((xmlCharEncoding)result->charset); } if (encoding != NULL) { xmlOutputBufferWriteString(buf, " encoding="); @@ -734,25 +742,13 @@ pa_xsltSaveResultToMem( } xmlOutputBufferWriteString(buf, "\n"); } + xmlOutputBufferFlush(buf); } - - if(buf) { - xmlOutputBufferFlush(buf); - if(buf->conv) { - doc_txt_len=buf->conv->use; - doc_txt_ptr=buf->conv->content; - } else { - doc_txt_len=buf->buffer->use; - doc_txt_ptr=buf->buffer->content; - } - - if(doc_txt_ptr && doc_txt_len) - doc_txt_ptr=BAD_CAST pa_strdup((const char*)doc_txt_ptr, doc_txt_len); - - xmlOutputBufferClose(buf); - } +finish: + return(buf->written - base); } + struct Xdoc2buf_result { char* str; size_t length; @@ -760,23 +756,33 @@ struct Xdoc2buf_result { static Xdoc2buf_result xdoc2buf(Request& r, VXdoc& vdoc, MethodParams& params, int index, VXdoc::Output_options& oo, - const String* file_spec) { + const String* file_spec, + bool use_source_charset_to_render_and_client_charset_to_write_to_header=false) { Xdoc2buf_result result; prepare_output_options(r, params, index, oo); - const char* encoding_cstr=oo.encoding->cstr(); - xmlCharEncodingHandler *encoder=xmlFindCharEncodingHandler(encoding_cstr); - if(!encoder) + const char* render_encoding; + const char* header_encoding; + if(use_source_charset_to_render_and_client_charset_to_write_to_header) { + render_encoding=r.charsets.source().NAME_CSTR(); + header_encoding=r.charsets.client().NAME_CSTR(); + } else { + header_encoding=render_encoding=oo.encoding->cstr(); + } + + xmlCharEncodingHandler *renderer=xmlFindCharEncodingHandler(render_encoding); + if(!renderer) throw Exception("parser.runtime", 0, - "encoding '%s' not supported", encoding_cstr); - // UTF-8 encoder contains empty input/output converters, + "encoding '%s' not supported", render_encoding); + // UTF-8 renderer contains empty input/output converters, // which is wrong for xmlOutputBufferCreateIO - // while zero encoder goes perfectly - const char* encoder_name=encoder->name; - if(strcmp(encoder_name, "UTF-8")==0) - encoder=0; + // while zero renderer goes perfectly + if(strcmp(render_encoding, "UTF-8")==0) + renderer=0; + + xmlOutputBuffer_auto_ptr outputBuffer(xmlAllocOutputBuffer(renderer)); xsltStylesheet_auto_ptr stylesheet(xsltNewStylesheet()); if(!stylesheet.get()) @@ -800,22 +806,31 @@ static Xdoc2buf_result xdoc2buf(Request& OOE2STYLE(omitXmlDeclaration); xmlDoc *document=gdome_xml_doc_get_xmlDoc(vdoc.get_document()); - document->encoding=BAD_CAST xmlMemStrdup(encoder_name); - - xmlChar* doc_txt_ptr=0; - int doc_txt_len=0; - pa_xsltSaveResultToMem(doc_txt_ptr, doc_txt_len, document, stylesheet.get(), encoder); - if(xmlHaveGenericErrors()) { + //document->encoding=BAD_CAST xmlMemStrdup(encoder_name); + if(pa_xsltSaveResultTo(outputBuffer.get(), document, stylesheet.get(), BAD_CAST header_encoding)<0 + || xmlHaveGenericErrors()) { GdomeException exc=0; throw XmlException(0, exc); } - result.length=doc_txt_len; - result.str=(char*)doc_txt_ptr; + // write out result + char *gnome_str; size_t gnome_length; + if(outputBuffer->conv) { + gnome_length=outputBuffer->conv->use; + gnome_str=(char *)outputBuffer->conv->content; + } else { + gnome_length=outputBuffer->buffer->use; + gnome_str=(char *)outputBuffer->buffer->content; + } + + if((result.length=gnome_length)) { + result.str=pa_strdup(gnome_str, gnome_length); + } else + result.str=0; if(file_spec) file_write(*file_spec, - result.str, result.length, + gnome_str, gnome_length, true/*as_text*/); return result; @@ -861,7 +876,8 @@ static void _string(Request& r, MethodPa VXdoc::Output_options oo(vdoc.output_options); Xdoc2buf_result buf=xdoc2buf(r, vdoc, params, 0, oo, - 0/*not to file, to memory*/); + 0/*not to file, to memory*/, + true/*use source charset to render, client charset to put to header*/); // write out result r.write_no_lang(String(buf.str, buf.length)); }