|
|
| version 1.19, 2001/09/13 14:10:54 | version 1.33, 2001/09/21 14:46:09 |
|---|---|
| Line 5 | Line 5 |
| Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf) | Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf) |
| */ | */ |
| static const char *RCSId="$Id$"; | #include "classes.h" |
| #ifdef XML | |
| #if _MSC_VER | static const char *RCSId="$Id$"; |
| # pragma warning(disable:4291) // disable warning | |
| // "no matching operator delete found; memory will not be freed if initialization throws an exception | |
| #endif | |
| #include "classes.h" | |
| #include "pa_request.h" | #include "pa_request.h" |
| #include "pa_vdom.h" | #include "pa_vdom.h" |
| #include "pa_xslt_stylesheet_manager.h" | |
| #include "pa_stylesheet_connection.h" | |
| #include "pa_vfile.h" | #include "pa_vfile.h" |
| #include "dnode.h" | |
| #include <strstream> | #include <strstream> |
| #include <Include/PlatformDefinitions.hpp> | #include <Include/PlatformDefinitions.hpp> |
| #include <util/PlatformUtils.hpp> | #include <util/PlatformUtils.hpp> |
| #include <util/XMLString.hpp> | |
| #include <XalanTransformer/XalanTransformer.hpp> | #include <XalanTransformer/XalanTransformer.hpp> |
| #include <XalanTransformer/XalanParsedSource.hpp> | #include <XalanTransformer/XalanParsedSource.hpp> |
| #include <PlatformSupport/XalanFileOutputStream.hpp> | |
| #include <PlatformSupport/XalanOutputStreamPrintWriter.hpp> | |
| #include <PlatformSupport/DOMStringPrintWriter.hpp> | |
| #include <XMLSupport/FormatterToXML.hpp> | #include <XMLSupport/FormatterToXML.hpp> |
| #include <XMLSupport/FormatterToHTML.hpp> | #include <XMLSupport/FormatterToHTML.hpp> |
| #include <XMLSupport/FormatterToText.hpp> | #include <XMLSupport/FormatterToText.hpp> |
| #include <XMLSupport/FormatterTreeWalker.hpp> | #include <XMLSupport/FormatterTreeWalker.hpp> |
| #include <PlatformSupport/XalanFileOutputStream.hpp> | |
| #include <PlatformSupport/XalanOutputStreamPrintWriter.hpp> | |
| #include <PlatformSupport/DOMStringPrintWriter.hpp> | |
| // defines | // defines |
| Line 46 static const char *RCSId="$Id$"; | Line 45 static const char *RCSId="$Id$"; |
| // class | // class |
| class MDom : public Methoded { | class MDom : public MDnode { |
| public: // VStateless_class | public: // VStateless_class |
| Value *create_new_value(Pool& pool) { return new(pool) VDom(pool); } | Value *create_new_value(Pool& pool) { return new(pool) VDom(pool); } |
| Line 59 public: // Methoded | Line 58 public: // Methoded |
| // methods | // methods |
| static void _set(Request& r, const String& method_name, MethodParams *params) { | |
| Pool& pool=r.pool(); | |
| VDom& vDom=*static_cast<VDom *>(r.self); | |
| Value& vxml=params->as_junction(0, "xml must be code"); | |
| Temp_lang temp_lang(r, String::UL_XML); | |
| const String& xml=r.process(vxml).as_string(); | |
| std::istrstream stream(xml.cstr()); | |
| XalanParsedSource* parsedSource; | |
| int error=vDom.get_transformer().parseSource(&stream, parsedSource); | |
| if(error) | |
| PTHROW(0, 0, | |
| &method_name, | |
| vDom.get_transformer().getLastError()); | |
| // replace any previous parsed source | |
| vDom.set_parsed_source(*parsedSource); | |
| } | |
| static void _load(Request& r, const String& method_name, MethodParams *params) { | |
| Pool& pool=r.pool(); | |
| VDom& vDom=*static_cast<VDom *>(r.self); | |
| // filespec | |
| const String& filename=params->as_string(0, "file name must not be code"); | |
| const char *filespec=r.absolute(filename).cstr(String::UL_FILE_NAME); | |
| XalanParsedSource* parsedSource; | |
| int error=vDom.get_transformer().parseSource(filespec, parsedSource); | |
| if(error) | |
| PTHROW(0, 0, | |
| &filename, | |
| vDom.get_transformer().getLastError()); | |
| // replace any previous parsed source | |
| vDom.set_parsed_source(*parsedSource); | |
| } | |
| const char *strX(const XalanDOMString& s) { | |
| return XMLString::transcode(s.c_str()); | |
| } | |
| static void _throw(Pool& pool, const String *source, const XSLException& e) { | |
| if(e.getURI().empty()) | |
| PTHROW(0, 0, | |
| source, | |
| "%s (%s)", | |
| strX(e.getMessage()), // message for exception | |
| strX(e.getType()) // type of exception | |
| ); | |
| else | |
| PTHROW(0, 0, | |
| source, | |
| "%s (%s) %s(%d:%d)'", | |
| strX(e.getMessage()), // message for exception | |
| strX(e.getType()), // type of exception | |
| strX(e.getURI()), // URI for the associated document, if any | |
| e.getLineNumber(), // line number, or -1 if unknown | |
| e.getColumnNumber() // column number, or -1 if unknown | |
| ); | |
| } | |
| class ParserStringXalanOutputStream: public XalanOutputStream { | class ParserStringXalanOutputStream: public XalanOutputStream { |
| public: | public: |
| Line 146 private: | Line 79 private: |
| }; | }; |
| static void create_optioned_listener( | |
| void create_optioned_listener( | const char *& content_type, const char *& charset, FormatterListener *& listener, |
| const char *& content_type, const char *& charset, FormatterListener *& listener, | Pool& pool, |
| Pool& pool, | const String& method_name, MethodParams *params, int index, Writer& writer) { |
| const String& method_name, MethodParams *params, int index, Writer& writer) { | // default encoding from pool |
| charset=0; | const String *scharset=&pool.get_charset(); |
| const String *method=0; | const String *method=0; |
| XalanDOMString xalan_encoding; | XalanDOMString xalan_encoding; |
| Value& voptions=params->as_no_junction(index, "options must not be code"); | if(params->size()>index) { |
| if(voptions.is_defined()) { | Value& voptions=params->as_no_junction(index, "options must not be code"); |
| if(Hash *options=voptions.get_hash()) { | if(voptions.is_defined()) { |
| // $.method[xml|html|text] | if(Hash *options=voptions.get_hash()) { |
| if(Value *vmethod=static_cast<Value *>(options->get(*new(pool) | // $.method[xml|html|text] |
| String(pool, DOM_OUTPUT_METHOD_OPTION_NAME)))) | if(Value *vmethod=static_cast<Value *>(options->get(*new(pool) |
| method=&vmethod->as_string(); | String(pool, DOM_OUTPUT_METHOD_OPTION_NAME)))) |
| method=&vmethod->as_string(); | |
| // $.encoding[windows-1251|...] | |
| if(Value *vencoding=static_cast<Value *>(options->get(*new(pool) | // $.encoding[windows-1251|...] |
| String(pool, DOM_OUTPUT_ENCODING_OPTION_NAME)))) { | if(Value *vencoding=static_cast<Value *>(options->get(*new(pool) |
| charset=vencoding->as_string().cstr(); | String(pool, DOM_OUTPUT_ENCODING_OPTION_NAME)))) { |
| xalan_encoding.append(charset, strlen(charset)); | scharset=&vencoding->as_string(); |
| } | } |
| } else | } else |
| PTHROW(0, 0, | PTHROW(0, 0, |
| &method_name, | &method_name, |
| "options must be hash"); | "options must be hash"); |
| } | |
| } | } |
| xalan_encoding.append(charset=scharset->cstr()); | |
| if(!method/*default='xml'*/ || *method == DOM_OUTPUT_METHOD_OPTION_VALUE_XML) { | if(!method/*default='xml'*/ || *method == DOM_OUTPUT_METHOD_OPTION_VALUE_XML) { |
| content_type="text/xml"; | content_type="text/xml"; |
| listener=new FormatterToXML(writer, | listener=new FormatterToXML(writer, |
| Line 211 void create_optioned_listener( | Line 146 void create_optioned_listener( |
| static void _save(Request& r, const String& method_name, MethodParams *params) { | static void _save(Request& r, const String& method_name, MethodParams *params) { |
| Pool& pool=r.pool(); | Pool& pool=r.pool(); |
| VDom& vDom=*static_cast<VDom *>(r.self); | VDnode& vnode=*static_cast<VDnode *>(r.self); |
| // filespec | // filespec |
| const String& filename=params->as_string(1, "file name must not be code"); | const String& file_name=params->as_string(0, "file name must not be code"); |
| const char *filespec=r.absolute(filename).cstr(String::UL_FILE_NAME); | const char *filespec=r.absolute(file_name).cstr(String::UL_FILE_SPEC); |
| // document | // node |
| XalanDocument& document=vDom.get_document(pool, &method_name); | XalanNode& node=vnode.get_node(pool, &method_name); |
| try { | try { |
| XalanFileOutputStream stream(XalanDOMString(filespec, strlen(filespec))); | XalanFileOutputStream stream(XalanDOMString(filespec, strlen(filespec))); |
| Line 226 static void _save(Request& r, const Stri | Line 161 static void _save(Request& r, const Stri |
| const char *content_type, *charset; | const char *content_type, *charset; |
| FormatterListener *formatterListener; | FormatterListener *formatterListener; |
| create_optioned_listener(content_type, charset, formatterListener, | create_optioned_listener(content_type, charset, formatterListener, |
| pool, method_name, params, 0, writer); | pool, method_name, params, 1, writer); |
| FormatterTreeWalker treeWalker(*formatterListener); | FormatterTreeWalker treeWalker(*formatterListener); |
| treeWalker.traverse(&document); // Walk the document and produce the XML... | treeWalker.traverse(&node); // Walk that node and produce the XML... |
| } catch(const XSLException& e) { | } catch(const XSLException& e) { |
| _throw(pool, &method_name, e); | r._throw(&method_name, e); |
| } | } |
| } | } |
| static void _string(Request& r, const String& method_name, MethodParams *params) { | static void _string(Request& r, const String& method_name, MethodParams *params) { |
| Pool& pool=r.pool(); | Pool& pool=r.pool(); |
| VDom& vDom=*static_cast<VDom *>(r.self); | VDnode& vnode=*static_cast<VDnode *>(r.self); |
| // document | // node |
| XalanDocument& document=vDom.get_document(pool, &method_name); | XalanNode& node=vnode.get_node(pool, &method_name); |
| try { | try { |
| String parserString=*new(pool) String(pool); | String parserString=*new(pool) String(pool); |
| Line 250 static void _string(Request& r, const St | Line 185 static void _string(Request& r, const St |
| create_optioned_listener(content_type, charset, formatterListener, | create_optioned_listener(content_type, charset, formatterListener, |
| pool, method_name, params, 0, writer); | pool, method_name, params, 0, writer); |
| FormatterTreeWalker treeWalker(*formatterListener); | FormatterTreeWalker treeWalker(*formatterListener); |
| treeWalker.traverse(&document); // Walk the document and produce the XML... | treeWalker.traverse(&node); // Walk that node and produce the XML... |
| // write out result | // write out result |
| r.write_no_lang(parserString); | r.write_no_lang(parserString); |
| } catch(const XSLException& e) { | } catch(const XSLException& e) { |
| _throw(pool, &method_name, e); | r._throw(&method_name, e); |
| } | } |
| } | } |
| static void _file(Request& r, const String& method_name, MethodParams *params) { | static void _file(Request& r, const String& method_name, MethodParams *params) { |
| Pool& pool=r.pool(); | Pool& pool=r.pool(); |
| VDom& vDom=*static_cast<VDom *>(r.self); | VDnode& vnode=*static_cast<VDnode *>(r.self); |
| // document | // node |
| XalanDocument& document=vDom.get_document(pool, &method_name); | XalanNode& node=vnode.get_node(pool, &method_name); |
| try { | try { |
| String& parserString=*new(pool) String(pool); | String& parserString=*new(pool) String(pool); |
| Line 276 static void _file(Request& r, const Stri | Line 211 static void _file(Request& r, const Stri |
| create_optioned_listener(content_type, charset, formatterListener, | create_optioned_listener(content_type, charset, formatterListener, |
| pool, method_name, params, 0, writer); | pool, method_name, params, 0, writer); |
| FormatterTreeWalker treeWalker(*formatterListener); | FormatterTreeWalker treeWalker(*formatterListener); |
| treeWalker.traverse(&document); // Walk the document and produce the XML... | treeWalker.traverse(&node); // Walk that node and produce the XML... |
| // write out result | // write out result |
| VFile& vfile=*new(pool) VFile(pool); | VFile& vfile=*new(pool) VFile(pool); |
| Line 291 static void _file(Request& r, const Stri | Line 226 static void _file(Request& r, const Stri |
| vcontent_type=vhcontent_type; | vcontent_type=vhcontent_type; |
| } else | } else |
| vcontent_type=new(pool) VString(*scontent_type); | vcontent_type=new(pool) VString(*scontent_type); |
| vfile.set(false/*tainted*/, cstr, strlen(cstr), 0/*filename*/, vcontent_type); | vfile.set(false/*tainted*/, cstr, strlen(cstr), 0/*file_name*/, vcontent_type); |
| r.write_no_lang(vfile); | r.write_no_lang(vfile); |
| } catch(const XSLException& e) { | } catch(const XSLException& e) { |
| _throw(pool, &method_name, e); | r._throw(&method_name, e); |
| } | } |
| } | } |
| static void _set(Request& r, const String& method_name, MethodParams *params) { | |
| Pool& pool=r.pool(); | |
| VDom& vdom=*static_cast<VDom *>(r.self); | |
| Value& vxml=params->as_junction(0, "xml must be code"); | |
| Temp_lang temp_lang(r, String::UL_XML); | |
| const String& xml=r.process(vxml).as_string(); | |
| std::istrstream stream(xml.cstr()); | |
| XalanParsedSource* parsedSource; | |
| int error=vdom.transformer().parseSource(&stream, parsedSource); | |
| if(error) | |
| PTHROW(0, 0, | |
| &method_name, | |
| vdom.transformer().getLastError()); | |
| // replace any previous parsed source | |
| vdom.set_parsed_source(*parsedSource); | |
| } | |
| static void _load(Request& r, const String& method_name, MethodParams *params) { | |
| Pool& pool=r.pool(); | |
| VDom& vdom=*static_cast<VDom *>(r.self); | |
| // filespec | |
| const String& file_name=params->as_string(0, "file name must not be code"); | |
| const char *filespec=r.absolute(file_name).cstr(String::UL_FILE_SPEC); | |
| XalanParsedSource* parsedSource; | |
| int error=vdom.transformer().parseSource(filespec, parsedSource); | |
| if(error) | |
| PTHROW(0, 0, | |
| &file_name, | |
| vdom.transformer().getLastError()); | |
| // replace any previous parsed source | |
| vdom.set_parsed_source(*parsedSource); | |
| } | |
| static void add_xslt_param(const Hash::Key& aattribute, Hash::Val *ameaning, | static void add_xslt_param(const Hash::Key& aattribute, Hash::Val *ameaning, |
| void *info) { | void *info) { |
| XalanTransformer& transformer=*static_cast<XalanTransformer *>(info); | XalanTransformer& transformer=*static_cast<XalanTransformer *>(info); |
| const char *attribute_cstr=aattribute.cstr(); | const char *attribute_cstr=aattribute.cstr(); |
| const char *meaning_cstr=static_cast<Value *>(ameaning)->as_string().cstr(); | const char *meaning_cstr=static_cast<Value *>(ameaning)->as_string().cstr(); |
| transformer.setStylesheetParam( | transformer.setStylesheetParam( |
| XalanDOMString(attribute_cstr, strlen(attribute_cstr)), | XalanDOMString(attribute_cstr), |
| XalanDOMString(meaning_cstr, strlen(meaning_cstr))); | XalanDOMString(meaning_cstr)); |
| } | } |
| static void _xslt(Request& r, const String& method_name, MethodParams *params) { | static void _xslt(Request& r, const String& method_name, MethodParams *params) { |
| Pool& pool=r.pool(); | Pool& pool=r.pool(); |
| VDom& vDom=*static_cast<VDom *>(r.self); | VDom& vdom=*static_cast<VDom *>(r.self); |
| // params | // params |
| if(params->size()>1) { | if(params->size()>1) { |
| Value& vparams=params->as_no_junction(1, "transform parameters parameter must not be code"); | Value& vparams=params->as_no_junction(1, "transform parameters parameter must not be code"); |
| if(vparams.is_defined()) | if(vparams.is_defined()) |
| if(Hash *params=vparams.get_hash()) | if(Hash *params=vparams.get_hash()) |
| params->for_each(add_xslt_param, &vDom.get_transformer()); | params->for_each(add_xslt_param, &vdom.transformer()); |
| else | else |
| PTHROW(0, 0, | PTHROW(0, 0, |
| &method_name, | &method_name, |
| Line 326 static void _xslt(Request& r, const Stri | Line 301 static void _xslt(Request& r, const Stri |
| } | } |
| // source | // source |
| XalanParsedSource &parsed_source=vDom.get_parsed_source(pool, &method_name); | XalanParsedSource &parsed_source=vdom.get_parsed_source(pool, &method_name); |
| // stylesheet | // stylesheet |
| const String& stylesheet_filename=params->as_string(0, "file name must not be code"); | const String& stylesheet_file_name=params->as_string(0, "file name must not be code"); |
| const char *stylesheet_filespec=r.absolute(stylesheet_filename).cstr(String::UL_FILE_NAME); | const String& stylesheet_filespec=r.absolute(stylesheet_file_name); |
| //_asm int 3; | |
| Stylesheet_connection& connection=XSLT_stylesheet_manager->get_connection(stylesheet_filespec); | |
| // target | // target |
| XalanDocument* target=vDom.get_parser_liaison().createDocument(); | XalanDocument* target=vdom.parser_liaison().createDocument(); |
| XSLTResultTarget domResultTarget(target); | XSLTResultTarget domResultTarget(target); |
| // transform | // transform |
| int error=vDom.get_transformer().transform(parsed_source, stylesheet_filespec, domResultTarget); | int error=vdom.transformer().transform( |
| parsed_source, | |
| &connection.stylesheet(), | |
| domResultTarget); | |
| connection.close(); | |
| if(error) | if(error) |
| PTHROW(0, 0, | PTHROW(0, 0, |
| &stylesheet_filename, | &stylesheet_file_name, |
| vDom.get_transformer().getLastError()); | vdom.transformer().getLastError()); |
| // write out result | // write out result |
| VDom& result=*new(pool) VDom(pool); | VDom& result=*new(pool) VDom(pool); |
| Line 351 static void _xslt(Request& r, const Stri | Line 332 static void _xslt(Request& r, const Stri |
| // constructor | // constructor |
| MDom::MDom(Pool& apool) : Methoded(apool) { | MDom::MDom(Pool& apool) : MDnode(apool) { |
| set_name(*NEW String(pool(), DOM_CLASS_NAME)); | set_name(*NEW String(pool(), DOM_CLASS_NAME)); |
| // ^dom.save[some.xml] | |
| // ^dom.save[some.xml;options hash] | |
| add_native_method("save", Method::CT_DYNAMIC, _save, 1, 2); | |
| // ^dom.string[] <doc/> | |
| // ^dom.string[options hash] <doc/> | |
| add_native_method("string", Method::CT_DYNAMIC, _string, 0, 1); | |
| // ^dom.file[] file with "<doc/>" | |
| // ^dom.file[options hash] file with "<doc/>" | |
| add_native_method("file", Method::CT_DYNAMIC, _file, 0, 1); | |
| // ^dom::set[<some>xml</some>] | // ^dom::set[<some>xml</some>] |
| add_native_method("set", Method::CT_DYNAMIC, _set, 1, 1); | add_native_method("set", Method::CT_DYNAMIC, _set, 1, 1); |
| // ^dom::load[some.xml] | // ^dom::load[some.xml] |
| add_native_method("load", Method::CT_DYNAMIC, _load, 1, 1); | add_native_method("load", Method::CT_DYNAMIC, _load, 1, 1); |
| // ^dom.save[options hash;some.xml] | // ^dom.xslt[stylesheet file_name] |
| add_native_method("save", Method::CT_DYNAMIC, _save, 2, 2); | // ^dom.xslt[stylesheet file_name;params hash] |
| // ^dom.string[options hash] <doc/> | |
| add_native_method("string", Method::CT_DYNAMIC, _string, 1, 1); | |
| // ^dom.file[options hash] file with "<doc/>" | |
| add_native_method("file", Method::CT_DYNAMIC, _file, 1, 1); | |
| // ^dom.xslt[stylesheet filename] | |
| // ^dom.xslt[stylesheet filename;params hash] | |
| add_native_method("xslt", Method::CT_DYNAMIC, _xslt, 1, 2); | add_native_method("xslt", Method::CT_DYNAMIC, _xslt, 1, 2); |
| } | } |
| Line 380 Methoded *Dom_class; | Line 364 Methoded *Dom_class; |
| // creator | // creator |
| Methoded *MDom_create(Pool& pool) { | #endif |
| // Use the static initializers to initialize the Xalan-C++ and Xerces-C++ platforms. | |
| // You must initialize Xerces-C++ once per process | |
| XMLPlatformUtils::Initialize(); | |
| XalanTransformer::initialize(); | |
| return Dom_class=new(pool) MDom(pool); | Methoded *MDom_create(Pool& pool) { |
| return | |
| #ifdef XML | |
| Dom_class=new(pool) MDom(pool); | |
| #else | |
| 0 | |
| #endif | |
| ; | |
| } | } |