|
|
| version 1.122, 2003/11/28 10:27:00 | version 1.143, 2004/03/01 12:12:28 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: @b xdoc parser class. | Parser: @b xdoc parser class. |
| Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001-2004 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| */ | */ |
| Line 13 static const char * const IDENT_XDOC_C=" | Line 13 static const char * const IDENT_XDOC_C=" |
| #include "gdome.h" | #include "gdome.h" |
| #include "libxml/tree.h" | #include "libxml/tree.h" |
| #include "libxml/HTMLtree.h" | |
| #include "libxslt/xsltInternals.h" | #include "libxslt/xsltInternals.h" |
| #include "libxslt/transform.h" | #include "libxslt/transform.h" |
| #include "libxslt/xsltutils.h" | #include "libxslt/xsltutils.h" |
| #include "libxslt/variables.h" | #include "libxslt/variables.h" |
| #include "libxslt/imports.h" | |
| #include "pa_vmethod_frame.h" | #include "pa_vmethod_frame.h" |
| Line 413 static void _create(Request& r, MethodPa | Line 414 static void _create(Request& r, MethodPa |
| Temp_lang temp_lang(r, String::L_XML); | Temp_lang temp_lang(r, String::L_XML); |
| const String& xml=r.process_to_string(param); | const String& xml=r.process_to_string(param); |
| const char* cstr=xml.cstr(String::L_UNSPECIFIED); | const char* cstr=xml.cstr(String::L_UNSPECIFIED, 0, &r.charsets); |
| document=(GdomeDocument *) | document=(GdomeDocument *) |
| gdome_xml_n_mkref((xmlNode *)xmlParseMemory( | gdome_xml_n_mkref((xmlNode *)xmlParseMemory( |
| cstr, strlen(cstr) | cstr, strlen(cstr) |
| Line 492 static void _load(Request& r, MethodPara | Line 493 static void _load(Request& r, MethodPara |
| /// todo!! add SAFE MODE!! | /// todo!! add SAFE MODE!! |
| GdomeDocument *document=(GdomeDocument *) | GdomeDocument *document=(GdomeDocument *) |
| gdome_xml_n_mkref((xmlNode *)xmlParseFile(uri->cstr())); | gdome_xml_n_mkref((xmlNode *)xmlParseFile(uri_cstr)); |
| if(!document || xmlHaveGenericErrors()) { | if(!document || xmlHaveGenericErrors()) { |
| GdomeException exc=0; | GdomeException exc=0; |
| throw XmlException(uri, exc); | throw XmlException(uri, exc); |
| Line 520 static void param_option_over_output_opt | Line 521 static void param_option_over_output_opt |
| } | } |
| static void param_option_over_output_option( | static void param_option_over_output_option( |
| HashStringValue& param_options, const char* option_name, | HashStringValue& param_options, const char* option_name, |
| bool& output_option) { | int& output_option) { |
| if(Value* value=param_options.get(String::Body(option_name))) { | if(Value* value=param_options.get(String::Body(option_name))) { |
| const String& s=value->as_string(); | const String& s=value->as_string(); |
| if(s=="yes") | if(s=="yes") |
| output_option=true; | output_option=1; |
| else if(s=="no") | else if(s=="no") |
| output_option=false; | output_option=0; |
| else | else |
| throw Exception("parser.runtime", | throw Exception("parser.runtime", |
| &s, | &s, |
| Line 569 static void prepare_output_options(Reque | Line 570 static void prepare_output_options(Reque |
| param_option_over_output_option(*options, "omit-xml-declaration", oo.omitXmlDeclaration); | param_option_over_output_option(*options, "omit-xml-declaration", oo.omitXmlDeclaration); |
| // $.standalone[yes|no] | // $.standalone[yes|no] |
| param_option_over_output_option(*options, "standalone", oo.standalone); | param_option_over_output_option(*options, "standalone", oo.standalone); |
| // $.doctype-public[?] | |
| param_option_over_output_option(*options, "doctype-public", oo.doctypePublic); | |
| // $.doctype-system[?] | |
| param_option_over_output_option(*options, "doctype-system", oo.doctypeSystem); | |
| // $.indent[yes|no] | // $.indent[yes|no] |
| param_option_over_output_option(*options, "indent", oo.indent); | param_option_over_output_option(*options, "indent", oo.indent); |
| // $.media-type[text/{html|xml|plain}] | // $.media-type[text/{html|xml|plain}] |
| Line 605 struct Xdoc2buf_result { | Line 602 struct Xdoc2buf_result { |
| static Xdoc2buf_result xdoc2buf(Request& r, VXdoc& vdoc, | static Xdoc2buf_result xdoc2buf(Request& r, VXdoc& vdoc, |
| MethodParams& params, int index, | MethodParams& params, int index, |
| VXdoc::Output_options& oo, | 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; | Xdoc2buf_result result; |
| prepare_output_options(r, params, index, | prepare_output_options(r, params, index, |
| oo); | oo); |
| const char* encoding_cstr=oo.encoding->cstr(); | const char* render_encoding; |
| xmlCharEncodingHandler *encoder=xmlFindCharEncodingHandler(encoding_cstr); | const char* header_encoding; |
| if(!encoder) | 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", | throw Exception("parser.runtime", |
| 0, | 0, |
| "encoding '%s' not supported", encoding_cstr); | "encoding '%s' not supported", render_encoding); |
| // UTF-8 encoder contains empty input/output converters, | // UTF-8 renderer contains empty input/output converters, |
| // which is wrong for xmlOutputBufferCreateIO | // which is wrong for xmlOutputBufferCreateIO |
| // while zero encoder goes perfectly | // while zero renderer goes perfectly |
| if(encoder && strcmp(encoder->name, "UTF-8")==0) | if(strcmp(render_encoding, "UTF-8")==0) |
| encoder=0; | renderer=0; |
| xmlOutputBuffer_auto_ptr outputBuffer(xmlAllocOutputBuffer(encoder)); | xmlOutputBuffer_auto_ptr outputBuffer(xmlAllocOutputBuffer(renderer)); |
| xsltStylesheet_auto_ptr stylesheet(xsltNewStylesheet()); | xsltStylesheet_auto_ptr stylesheet(xsltNewStylesheet()); |
| if(!stylesheet.get()) | if(!stylesheet.get()) |
| Line 630 static Xdoc2buf_result xdoc2buf(Request& | Line 636 static Xdoc2buf_result xdoc2buf(Request& |
| 0, | 0, |
| "xsltNewStylesheet failed"); | "xsltNewStylesheet failed"); |
| #define OOS2STYLE(name) \ | #define OOSTRING2STYLE(name) \ |
| stylesheet->name=oo.name?BAD_CAST xmlMemStrdup(r.transcode(*oo.name)->str):0 | stylesheet->name=oo.name?BAD_CAST xmlMemStrdup(r.transcode(*oo.name)->str):0 |
| #define OOE2STYLE(name) \ | #define OOBOOL2STYLE(name) \ |
| stylesheet->name=oo.name | if(oo.name>=0) stylesheet->name=oo.name |
| OOS2STYLE(method); | OOSTRING2STYLE(method); |
| OOS2STYLE(encoding); | OOSTRING2STYLE(encoding); |
| OOS2STYLE(mediaType); | OOSTRING2STYLE(mediaType); |
| OOS2STYLE(doctypeSystem); | // OOSTRING2STYLE(doctypeSystem); |
| OOS2STYLE(doctypePublic); | // OOSTRING2STYLE(doctypePublic); |
| OOE2STYLE(indent); | OOBOOL2STYLE(indent); |
| OOS2STYLE(version); | OOSTRING2STYLE(version); |
| OOE2STYLE(standalone); | OOBOOL2STYLE(standalone); |
| OOE2STYLE(omitXmlDeclaration); | OOBOOL2STYLE(omitXmlDeclaration); |
| xmlDoc *document=gdome_xml_doc_get_xmlDoc(vdoc.get_document()); | xmlDoc *document=gdome_xml_doc_get_xmlDoc(vdoc.get_document()); |
| if(xsltSaveResultTo(outputBuffer.get(), document, stylesheet.get())<0) { | document->encoding=BAD_CAST xmlMemStrdup(render_encoding); |
| if(header_encoding) | |
| stylesheet->encoding=BAD_CAST xmlMemStrdup(header_encoding); | |
| if(xsltSaveResultTo(outputBuffer.get(), document, stylesheet.get())<0 | |
| || xmlHaveGenericErrors()) { | |
| GdomeException exc=0; | GdomeException exc=0; |
| throw XmlException(0, exc); | throw XmlException(0, exc); |
| } | } |
| Line 714 static void _string(Request& r, MethodPa | Line 724 static void _string(Request& r, MethodPa |
| VXdoc::Output_options oo(vdoc.output_options); | VXdoc::Output_options oo(vdoc.output_options); |
| Xdoc2buf_result buf=xdoc2buf(r, vdoc, params, 0, | Xdoc2buf_result buf=xdoc2buf(r, vdoc, params, 0, |
| oo, | 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 | // write out result |
| r.write_no_lang(String(buf.str, buf.length)); | r.write_no_lang(String(buf.str, buf.length)); |
| } | } |
| Line 734 static void add_xslt_param( | Line 745 static void add_xslt_param( |
| *info->current_transform_param++=(s=info->r->transcode(attribute))->str; *info->strings+=s; | *info->current_transform_param++=(s=info->r->transcode(attribute))->str; *info->strings+=s; |
| *info->current_transform_param++=(s=info->r->transcode(meaning->as_string()))->str; *info->strings+=s; | *info->current_transform_param++=(s=info->r->transcode(meaning->as_string()))->str; *info->strings+=s; |
| } | } |
| static VXdoc& _transform(Request& r, const String* stylesheet_source, | static VXdoc& _transform(Request& r, const String* stylesheet_source, |
| VXdoc& vdoc, xsltStylesheetPtr stylesheet, const char** transform_params) { | VXdoc& vdoc, xsltStylesheetPtr stylesheet, const char** transform_params) |
| { | |
| xmlDoc *document=gdome_xml_doc_get_xmlDoc(vdoc.get_document()); | xmlDoc *document=gdome_xml_doc_get_xmlDoc(vdoc.get_document()); |
| xsltTransformContext_auto_ptr transformContext( | xsltTransformContext_auto_ptr transformContext( |
| xsltNewTransformContext(stylesheet, document)); | xsltNewTransformContext(stylesheet, document)); |
| Line 785 static VXdoc& _transform(Request& r, con | Line 798 static VXdoc& _transform(Request& r, con |
| oo.method=stylesheet->method?&r.transcode(stylesheet->method):0; | oo.method=stylesheet->method?&r.transcode(stylesheet->method):0; |
| oo.encoding=stylesheet->encoding?&r.transcode(stylesheet->encoding):0; | oo.encoding=stylesheet->encoding?&r.transcode(stylesheet->encoding):0; |
| oo.mediaType=stylesheet->mediaType?&r.transcode(stylesheet->mediaType):0; | oo.mediaType=stylesheet->mediaType?&r.transcode(stylesheet->mediaType):0; |
| oo.doctypeSystem=stylesheet->doctypeSystem?&r.transcode(stylesheet->doctypeSystem):0; | oo.indent=stylesheet->indent; |
| oo.doctypePublic=stylesheet->doctypePublic?&r.transcode(stylesheet->doctypePublic):0; | |
| oo.indent=stylesheet->indent!=0; | |
| oo.version=stylesheet->version?&r.transcode(stylesheet->version):0; | oo.version=stylesheet->version?&r.transcode(stylesheet->version):0; |
| oo.standalone=stylesheet->standalone!=0; | oo.standalone=stylesheet->standalone; |
| oo.omitXmlDeclaration=stylesheet->omitXmlDeclaration!=0; | oo.omitXmlDeclaration=stylesheet->omitXmlDeclaration; |
| // return | // return |
| return result; | return result; |
| Line 825 static void _transform(Request& r, Metho | Line 836 static void _transform(Request& r, Metho |
| static_cast<VXdoc *>(vxdoc)->get_document()); | static_cast<VXdoc *>(vxdoc)->get_document()); |
| // compile xdoc stylesheet | // compile xdoc stylesheet |
| xsltStylesheet_auto_ptr stylesheet_ptr(xsltParseStylesheetDoc(document)); | xsltStylesheet_auto_ptr stylesheet_ptr(xsltParseStylesheetDoc(document)); |
| // strange thing - xsltParseStylesheetDoc records document and destroys it in stylesheet destructor | |
| // we don't need that | |
| stylesheet_ptr->doc=0; | |
| if(xmlHaveGenericErrors()) { | if(xmlHaveGenericErrors()) { |
| GdomeException exc=0; | GdomeException exc=0; |
| throw XmlException(0, exc); | throw XmlException(0, exc); |
| Line 836 static void _transform(Request& r, Metho | Line 844 static void _transform(Request& r, Metho |
| throw Exception("xml", | throw Exception("xml", |
| 0, | 0, |
| "stylesheet failed to compile"); | "stylesheet failed to compile"); |
| // strange thing - xsltParseStylesheetDoc records document and destroys it in stylesheet destructor | |
| // we don't need that | |
| stylesheet_ptr->doc=0; | |
| // transform! | // transform! |
| result=&_transform(r, 0, | result=&_transform(r, 0, |
| Line 845 static void _transform(Request& r, Metho | Line 856 static void _transform(Request& r, Metho |
| // extablish stylesheet connection | // extablish stylesheet connection |
| const String& stylesheet_filespec= | const String& stylesheet_filespec= |
| r.absolute(params.as_string(0, "stylesheet must be file name (string) or DOM document (xdoc)")); | r.absolute(params.as_string(0, "stylesheet must be file name (string) or DOM document (xdoc)")); |
| Stylesheet_connection_ptr connection=stylesheet_manager.get_connection(stylesheet_filespec); | Stylesheet_connection_ptr connection=stylesheet_manager->get_connection(stylesheet_filespec); |
| // load and compile file to stylesheet [or get cached if any] | // load and compile file to stylesheet [or get cached if any] |
| // transform! | // transform! |