|
|
| version 1.25, 2001/09/18 16:05:42 | version 1.32, 2001/09/21 09:04:18 |
|---|---|
| Line 7 | Line 7 |
| */ | */ |
| static const char *RCSId="$Id$"; | static const char *RCSId="$Id$"; |
| #if _MSC_VER | |
| # 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 "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_xslt_stylesheet_manager.h" |
| #include "pa_stylesheet_connection.h" | #include "pa_stylesheet_connection.h" |
| #include "pa_vfile.h" | |
| #include "dnode.h" | #include "dnode.h" |
| #include <strstream> | #include <strstream> |
| Line 24 static const char *RCSId="$Id$"; | Line 20 static const char *RCSId="$Id$"; |
| #include <util/PlatformUtils.hpp> | #include <util/PlatformUtils.hpp> |
| #include <XalanTransformer/XalanTransformer.hpp> | #include <XalanTransformer/XalanTransformer.hpp> |
| #include <XalanTransformer/XalanParsedSource.hpp> | #include <XalanTransformer/XalanParsedSource.hpp> |
| #include <XMLSupport/FormatterToXML.hpp> | |
| #include <XMLSupport/FormatterToHTML.hpp> | |
| #include <XMLSupport/FormatterToText.hpp> | |
| #include <XMLSupport/FormatterTreeWalker.hpp> | |
| #include <PlatformSupport/XalanFileOutputStream.hpp> | |
| #include <PlatformSupport/XalanOutputStreamPrintWriter.hpp> | |
| #include <PlatformSupport/DOMStringPrintWriter.hpp> | |
| // defines | // defines |
| #define DOM_CLASS_NAME "dom" | #define DOM_CLASS_NAME "dom" |
| #define DOM_OUTPUT_METHOD_OPTION_NAME "method" | |
| #define DOM_OUTPUT_METHOD_OPTION_VALUE_XML "xml" | |
| #define DOM_OUTPUT_METHOD_OPTION_VALUE_HTML "html" | |
| #define DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT "text" | |
| #define DOM_OUTPUT_ENCODING_OPTION_NAME "encoding" | |
| #define DOM_OUTPUT_DEFAULT_INDENT 4 | |
| // class | // class |
| class MDom : public MDnode { | class MDom : public MDnode { |
| Line 44 public: // Methoded | Line 56 public: // Methoded |
| // methods | // methods |
| class ParserStringXalanOutputStream: public XalanOutputStream { | |
| public: | |
| explicit ParserStringXalanOutputStream(String& astring) : fstring(astring) {} | |
| protected: // XalanOutputStream | |
| virtual void writeData(const char *theBuffer, unsigned long theBufferLength) { | |
| char *copy=(char *)fstring.malloc((size_t)theBufferLength); | |
| memcpy(copy, theBuffer, (size_t)theBufferLength); | |
| fstring.APPEND_CLEAN(copy, (size_t)theBufferLength, "dom", -1); | |
| } | |
| virtual void doFlush() {} | |
| private: | |
| String& fstring; | |
| }; | |
| static void create_optioned_listener( | |
| const char *& content_type, const char *& charset, FormatterListener *& listener, | |
| Pool& pool, | |
| const String& method_name, MethodParams *params, int index, Writer& writer) { | |
| // default encoding from pool | |
| const String *scharset=&pool.get_charset(); | |
| const String *method=0; | |
| XalanDOMString xalan_encoding; | |
| if(params->size()>index) { | |
| Value& voptions=params->as_no_junction(index, "options must not be code"); | |
| if(voptions.is_defined()) { | |
| if(Hash *options=voptions.get_hash()) { | |
| // $.method[xml|html|text] | |
| if(Value *vmethod=static_cast<Value *>(options->get(*new(pool) | |
| String(pool, DOM_OUTPUT_METHOD_OPTION_NAME)))) | |
| method=&vmethod->as_string(); | |
| // $.encoding[windows-1251|...] | |
| if(Value *vencoding=static_cast<Value *>(options->get(*new(pool) | |
| String(pool, DOM_OUTPUT_ENCODING_OPTION_NAME)))) { | |
| scharset=&vencoding->as_string(); | |
| } | |
| } else | |
| PTHROW(0, 0, | |
| &method_name, | |
| "options must be hash"); | |
| } | |
| } | |
| xalan_encoding.append(charset=scharset->cstr()); | |
| if(!method/*default='xml'*/ || *method == DOM_OUTPUT_METHOD_OPTION_VALUE_XML) { | |
| content_type="text/xml"; | |
| listener=new FormatterToXML(writer, | |
| XalanDOMString(), // version | |
| true, // doIndent | |
| DOM_OUTPUT_DEFAULT_INDENT, // indent | |
| xalan_encoding // encoding | |
| ); | |
| } else if(*method == DOM_OUTPUT_METHOD_OPTION_VALUE_HTML) { | |
| content_type="text/html"; | |
| listener=new FormatterToHTML(writer, | |
| xalan_encoding, // encoding | |
| XalanDOMString(), // mediaType | |
| XalanDOMString(), // doctypeSystem; String to be printed at the top of the document | |
| XalanDOMString(), // doctypePublic | |
| true, // doIndent | |
| DOM_OUTPUT_DEFAULT_INDENT // indent | |
| ); | |
| } else if(*method == DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT) { | |
| content_type="text/plain"; | |
| listener=new FormatterToText(writer, | |
| xalan_encoding // encoding | |
| ); | |
| } else | |
| PTHROW(0, 0, | |
| method, | |
| DOM_OUTPUT_METHOD_OPTION_NAME " option is invalid; valid methods are: " | |
| "'" DOM_OUTPUT_METHOD_OPTION_VALUE_XML "', " | |
| "'" DOM_OUTPUT_METHOD_OPTION_VALUE_HTML "', " | |
| "'" DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT "'"); | |
| // never reached | |
| } | |
| static void _save(Request& r, const String& method_name, MethodParams *params) { | |
| Pool& pool=r.pool(); | |
| VDnode& vnode=*static_cast<VDnode *>(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); | |
| // node | |
| XalanNode& node=vnode.get_node(pool, &method_name); | |
| try { | |
| XalanFileOutputStream stream(XalanDOMString(filespec, strlen(filespec))); | |
| XalanOutputStreamPrintWriter writer(stream); | |
| const char *content_type, *charset; | |
| FormatterListener *formatterListener; | |
| create_optioned_listener(content_type, charset, formatterListener, | |
| pool, method_name, params, 1, writer); | |
| FormatterTreeWalker treeWalker(*formatterListener); | |
| treeWalker.traverse(&node); // Walk that node and produce the XML... | |
| } catch(const XSLException& e) { | |
| r._throw(&method_name, e); | |
| } | |
| } | |
| static void _string(Request& r, const String& method_name, MethodParams *params) { | |
| Pool& pool=r.pool(); | |
| VDnode& vnode=*static_cast<VDnode *>(r.self); | |
| // node | |
| XalanNode& node=vnode.get_node(pool, &method_name); | |
| try { | |
| String parserString=*new(pool) String(pool); | |
| ParserStringXalanOutputStream stream(parserString); | |
| XalanOutputStreamPrintWriter writer(stream); | |
| const char *content_type, *charset; | |
| FormatterListener *formatterListener; | |
| create_optioned_listener(content_type, charset, formatterListener, | |
| pool, method_name, params, 0, writer); | |
| FormatterTreeWalker treeWalker(*formatterListener); | |
| treeWalker.traverse(&node); // Walk that node and produce the XML... | |
| // write out result | |
| r.write_no_lang(parserString); | |
| } catch(const XSLException& e) { | |
| r._throw(&method_name, e); | |
| } | |
| } | |
| static void _file(Request& r, const String& method_name, MethodParams *params) { | |
| Pool& pool=r.pool(); | |
| VDnode& vnode=*static_cast<VDnode *>(r.self); | |
| // node | |
| XalanNode& node=vnode.get_node(pool, &method_name); | |
| try { | |
| String& parserString=*new(pool) String(pool); | |
| ParserStringXalanOutputStream stream(parserString); | |
| XalanOutputStreamPrintWriter writer(stream); | |
| const char *content_type, *charset; | |
| FormatterListener *formatterListener; | |
| create_optioned_listener(content_type, charset, formatterListener, | |
| pool, method_name, params, 0, writer); | |
| FormatterTreeWalker treeWalker(*formatterListener); | |
| treeWalker.traverse(&node); // Walk that node and produce the XML... | |
| // write out result | |
| VFile& vfile=*new(pool) VFile(pool); | |
| const char *cstr=parserString.cstr(); | |
| String *scontent_type=new(pool) String(pool, content_type); | |
| Value *vcontent_type; | |
| if(charset) { | |
| VHash *vhcontent_type=new(pool) VHash(pool); | |
| vhcontent_type->hash().put(*value_name, new(pool) VString(*scontent_type)); | |
| String *scharset=new(pool) String(pool, charset); | |
| vhcontent_type->hash().put(*new(pool) String(pool, "charset"), new(pool) VString(*scharset)); | |
| vcontent_type=vhcontent_type; | |
| } else | |
| vcontent_type=new(pool) VString(*scontent_type); | |
| vfile.set(false/*tainted*/, cstr, strlen(cstr), 0/*file_name*/, vcontent_type); | |
| r.write_no_lang(vfile); | |
| } catch(const XSLException& e) { | |
| r._throw(&method_name, e); | |
| } | |
| } | |
| static void _set(Request& r, const String& method_name, MethodParams *params) { | static void _set(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); |
| Value& vxml=params->as_junction(0, "xml must be code"); | Value& vxml=params->as_junction(0, "xml must be code"); |
| Temp_lang temp_lang(r, String::UL_XML); | Temp_lang temp_lang(r, String::UL_XML); |
| Line 54 static void _set(Request& r, const Strin | Line 241 static void _set(Request& r, const Strin |
| std::istrstream stream(xml.cstr()); | std::istrstream stream(xml.cstr()); |
| XalanParsedSource* parsedSource; | XalanParsedSource* parsedSource; |
| int error=vDom.transformer().parseSource(&stream, parsedSource); | int error=vdom.transformer().parseSource(&stream, parsedSource); |
| if(error) | if(error) |
| PTHROW(0, 0, | PTHROW(0, 0, |
| &method_name, | &method_name, |
| vDom.transformer().getLastError()); | vdom.transformer().getLastError()); |
| // replace any previous parsed source | // replace any previous parsed source |
| vDom.set_parsed_source(*parsedSource); | vdom.set_parsed_source(*parsedSource); |
| } | } |
| static void _load(Request& r, const String& method_name, MethodParams *params) { | static void _load(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); |
| // filespec | // filespec |
| const String& file_name=params->as_string(0, "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(file_name).cstr(String::UL_FILE_SPEC); | const char *filespec=r.absolute(file_name).cstr(String::UL_FILE_SPEC); |
| XalanParsedSource* parsedSource; | XalanParsedSource* parsedSource; |
| int error=vDom.transformer().parseSource(filespec, parsedSource); | int error=vdom.transformer().parseSource(filespec, parsedSource); |
| if(error) | if(error) |
| PTHROW(0, 0, | PTHROW(0, 0, |
| &file_name, | &file_name, |
| vDom.transformer().getLastError()); | vdom.transformer().getLastError()); |
| // replace any previous parsed source | // replace any previous parsed source |
| vDom.set_parsed_source(*parsedSource); | 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, |
| Line 97 static void add_xslt_param(const Hash::K | Line 284 static void add_xslt_param(const Hash::K |
| } | } |
| 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.transformer()); | params->for_each(add_xslt_param, &vdom.transformer()); |
| else | else |
| PTHROW(0, 0, | PTHROW(0, 0, |
| &method_name, | &method_name, |
| Line 112 static void _xslt(Request& r, const Stri | Line 299 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_file_name=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"); |
| Line 121 static void _xslt(Request& r, const Stri | Line 308 static void _xslt(Request& r, const Stri |
| Stylesheet_connection& connection=XSLT_stylesheet_manager->get_connection(stylesheet_filespec); | Stylesheet_connection& connection=XSLT_stylesheet_manager->get_connection(stylesheet_filespec); |
| // target | // target |
| XalanDocument* target=vDom.parser_liaison().createDocument(); | XalanDocument* target=vdom.parser_liaison().createDocument(); |
| XSLTResultTarget domResultTarget(target); | XSLTResultTarget domResultTarget(target); |
| // transform | // transform |
| int error=vDom.transformer().transform( | int error=vdom.transformer().transform( |
| parsed_source, | parsed_source, |
| &connection.stylesheet(), | &connection.stylesheet(), |
| domResultTarget); | domResultTarget); |
| Line 133 static void _xslt(Request& r, const Stri | Line 320 static void _xslt(Request& r, const Stri |
| if(error) | if(error) |
| PTHROW(0, 0, | PTHROW(0, 0, |
| &stylesheet_file_name, | &stylesheet_file_name, |
| vDom.transformer().getLastError()); | vdom.transformer().getLastError()); |
| // write out result | // write out result |
| VDom& result=*new(pool) VDom(pool); | VDom& result=*new(pool) VDom(pool); |
| Line 146 static void _xslt(Request& r, const Stri | Line 333 static void _xslt(Request& r, const Stri |
| MDom::MDom(Pool& apool) : MDnode(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); |