Annotation of parser3/src/classes/xdoc.C, revision 1.1

1.1     ! parser      1: /** @file
        !             2:        Parser: @b dom parser class.
        !             3: 
        !             4:        Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
        !             5:        Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
        !             6: 
        !             7:        $Id: dom.C,v 1.35 2001/09/26 10:32:25 parser Exp $
        !             8: */
        !             9: #include "classes.h"
        !            10: #ifdef XML
        !            11: 
        !            12: #include "pa_request.h"
        !            13: #include "pa_vxdoc.h"
        !            14: #include "pa_xslt_stylesheet_manager.h"
        !            15: #include "pa_stylesheet_connection.h"
        !            16: #include "pa_vfile.h"
        !            17: #include "xnode.h"
        !            18: 
        !            19: #include <strstream>
        !            20: #include <Include/PlatformDefinitions.hpp>
        !            21: #include <util/PlatformUtils.hpp>
        !            22: #include <XalanTransformer/XalanTransformer.hpp>
        !            23: #include <XalanTransformer/XalanParsedSource.hpp>
        !            24: #include <XMLSupport/FormatterToXML.hpp>
        !            25: #include <XMLSupport/FormatterToHTML.hpp>
        !            26: #include <XMLSupport/FormatterToText.hpp>
        !            27: #include <XMLSupport/FormatterTreeWalker.hpp>
        !            28: #include <PlatformSupport/XalanFileOutputStream.hpp>
        !            29: #include <PlatformSupport/XalanOutputStreamPrintWriter.hpp>
        !            30: #include <PlatformSupport/DOMStringPrintWriter.hpp>
        !            31: 
        !            32: // defines
        !            33: 
        !            34: #define XDOC_CLASS_NAME "xdoc"
        !            35: 
        !            36: #define XDOC_OUTPUT_METHOD_OPTION_NAME "method"
        !            37: #define XDOC_OUTPUT_METHOD_OPTION_VALUE_XML "xml"
        !            38: #define XDOC_OUTPUT_METHOD_OPTION_VALUE_HTML "html"
        !            39: #define XDOC_OUTPUT_METHOD_OPTION_VALUE_TEXT "text"
        !            40: 
        !            41: #define XDOC_OUTPUT_ENCODING_OPTION_NAME "encoding"
        !            42: 
        !            43: #define XDOC_OUTPUT_DEFAULT_INDENT 4
        !            44: 
        !            45: // class
        !            46: 
        !            47: class MXdoc : public MXnode {
        !            48: public: // VStateless_class
        !            49:        Value *create_new_value(Pool& pool) { return new(pool) VXdoc(pool); }
        !            50: 
        !            51: public:
        !            52:        MXdoc(Pool& pool);
        !            53: 
        !            54: public: // Methoded
        !            55:        bool used_directly() { return true; }
        !            56: };
        !            57: 
        !            58: // methods
        !            59: 
        !            60: class ParserStringXalanOutputStream: public XalanOutputStream {
        !            61: public:
        !            62:        
        !            63:        explicit ParserStringXalanOutputStream(String& astring) : fstring(astring) {}
        !            64: 
        !            65: protected: // XalanOutputStream
        !            66: 
        !            67:        virtual void writeData(const char *theBuffer, unsigned long theBufferLength) {
        !            68:                char *copy=(char *)fstring.malloc((size_t)theBufferLength);
        !            69:                memcpy(copy, theBuffer, (size_t)theBufferLength);
        !            70:                fstring.APPEND_CLEAN(copy, (size_t)theBufferLength, "dom", 0);
        !            71:        }
        !            72: 
        !            73:        virtual void doFlush() {}
        !            74: 
        !            75: private:
        !            76: 
        !            77:        String& fstring;
        !            78:        
        !            79: };
        !            80: 
        !            81: static void create_optioned_listener(
        !            82:                                                                         const char *& content_type, const char *& charset, FormatterListener *& listener, 
        !            83:                                                                         Pool& pool, 
        !            84:                                                                         const String& method_name, MethodParams *params, int index, Writer& writer) {
        !            85:        // default encoding from pool
        !            86:        const String *scharset=&pool.get_charset();
        !            87:        const String *method=0;
        !            88:        XalanDOMString xalan_encoding;
        !            89: 
        !            90:        if(params->size()>index) {
        !            91:                Value& voptions=params->as_no_junction(index, "options must not be code");
        !            92:                if(voptions.is_defined()) {
        !            93:                        if(Hash *options=voptions.get_hash()) {
        !            94:                                // $.method[xml|html|text]
        !            95:                                if(Value *vmethod=static_cast<Value *>(options->get(*new(pool) 
        !            96:                                        String(pool, XDOC_OUTPUT_METHOD_OPTION_NAME))))
        !            97:                                        method=&vmethod->as_string();
        !            98: 
        !            99:                                // $.encoding[windows-1251|...]
        !           100:                                if(Value *vencoding=static_cast<Value *>(options->get(*new(pool) 
        !           101:                                        String(pool, XDOC_OUTPUT_ENCODING_OPTION_NAME)))) {
        !           102:                                        scharset=&vencoding->as_string();
        !           103:                                }
        !           104:                        } else
        !           105:                                PTHROW(0, 0,
        !           106:                                        &method_name,
        !           107:                                        "options must be hash");
        !           108:                }
        !           109:        }
        !           110: 
        !           111:        xalan_encoding.append(charset=scharset->cstr());
        !           112:        if(!method/*default='xml'*/ || *method == XDOC_OUTPUT_METHOD_OPTION_VALUE_XML) {
        !           113:                content_type="text/xml";
        !           114:                listener=new FormatterToXML(writer,
        !           115:                        XalanDOMString(),  // version
        !           116:                        true, // doIndent
        !           117:                        XDOC_OUTPUT_DEFAULT_INDENT, // indent 
        !           118:                        xalan_encoding  // encoding
        !           119:                );
        !           120:        } else if(*method == XDOC_OUTPUT_METHOD_OPTION_VALUE_HTML) {
        !           121:                content_type="text/html";
        !           122:                listener=new FormatterToHTML(writer,
        !           123:                        xalan_encoding,  // encoding
        !           124:                        XalanDOMString(),  // mediaType 
        !           125:                        XalanDOMString(),  // doctypeSystem; String to be printed at the top of the document 
        !           126:                        XalanDOMString(),  // doctypePublic  
        !           127:                        true, // doIndent 
        !           128:                        XDOC_OUTPUT_DEFAULT_INDENT // indent 
        !           129:                );
        !           130:        } else if(*method == XDOC_OUTPUT_METHOD_OPTION_VALUE_TEXT) {
        !           131:                content_type="text/plain";
        !           132:                listener=new FormatterToText(writer,
        !           133:                        xalan_encoding  // encoding
        !           134:                );
        !           135:        } else
        !           136:                PTHROW(0, 0,
        !           137:                        method,
        !           138:                        XDOC_OUTPUT_METHOD_OPTION_NAME " option is invalid; valid methods are: "
        !           139:                                "'" XDOC_OUTPUT_METHOD_OPTION_VALUE_XML "', "
        !           140:                                "'" XDOC_OUTPUT_METHOD_OPTION_VALUE_HTML "', "
        !           141:                                "'" XDOC_OUTPUT_METHOD_OPTION_VALUE_TEXT "'");                  
        !           142: 
        !           143:        // never reached
        !           144: }
        !           145: 
        !           146: static void _save(Request& r, const String& method_name, MethodParams *params) {
        !           147:        Pool& pool=r.pool();
        !           148:        VXnode& vnode=*static_cast<VXnode *>(r.self);
        !           149: 
        !           150:        // filespec
        !           151:        const String& file_name=params->as_string(0, "file name must not be code");
        !           152:        const char *filespec=r.absolute(file_name).cstr(String::UL_FILE_SPEC);
        !           153:        
        !           154:        // node
        !           155:        XalanNode& node=vnode.get_node(pool, &method_name);
        !           156: 
        !           157:        try {
        !           158:                XalanFileOutputStream stream(XalanDOMString(filespec, strlen(filespec)));
        !           159:                XalanOutputStreamPrintWriter writer(stream);
        !           160:                const char *content_type, *charset;
        !           161:                FormatterListener *formatterListener;
        !           162:                create_optioned_listener(content_type, charset, formatterListener, 
        !           163:                        pool, method_name, params, 1, writer);
        !           164:                FormatterTreeWalker treeWalker(*formatterListener);
        !           165:                treeWalker.traverse(&node); // Walk that node and produce the XML...
        !           166:        } catch(const XSLException& e) {
        !           167:                r._throw(&method_name, e);
        !           168:        }
        !           169: }
        !           170: 
        !           171: static void _string(Request& r, const String& method_name, MethodParams *params) {
        !           172:        Pool& pool=r.pool();
        !           173:        VXnode& vnode=*static_cast<VXnode *>(r.self);
        !           174: 
        !           175:        // node
        !           176:        XalanNode& node=vnode.get_node(pool, &method_name);
        !           177: 
        !           178:        try {
        !           179:                String parserString=*new(pool) String(pool);
        !           180:                ParserStringXalanOutputStream stream(parserString);
        !           181:                XalanOutputStreamPrintWriter writer(stream);
        !           182:                const char *content_type, *charset;
        !           183:                FormatterListener *formatterListener;
        !           184:                create_optioned_listener(content_type, charset, formatterListener, 
        !           185:                        pool, method_name, params, 0, writer);
        !           186:                FormatterTreeWalker treeWalker(*formatterListener);
        !           187:                treeWalker.traverse(&node); // Walk that node and produce the XML...
        !           188: 
        !           189:                // write out result
        !           190:                r.write_no_lang(parserString);
        !           191:        } catch(const XSLException& e) {
        !           192:                r._throw(&method_name, e);
        !           193:        }
        !           194: }
        !           195: 
        !           196: 
        !           197: static void _file(Request& r, const String& method_name, MethodParams *params) {
        !           198:        Pool& pool=r.pool();
        !           199:        VXnode& vnode=*static_cast<VXnode *>(r.self);
        !           200: 
        !           201:        // node
        !           202:        XalanNode& node=vnode.get_node(pool, &method_name);
        !           203: 
        !           204:        try {
        !           205:                String& parserString=*new(pool) String(pool);
        !           206:                ParserStringXalanOutputStream stream(parserString);
        !           207:                XalanOutputStreamPrintWriter writer(stream);
        !           208:                const char *content_type, *charset;
        !           209:                FormatterListener *formatterListener;
        !           210:                create_optioned_listener(content_type, charset, formatterListener, 
        !           211:                        pool, method_name, params, 0, writer);
        !           212:                FormatterTreeWalker treeWalker(*formatterListener);
        !           213:                treeWalker.traverse(&node); // Walk that node and produce the XML...
        !           214: 
        !           215:                // write out result
        !           216:                VFile& vfile=*new(pool) VFile(pool);
        !           217:                const char *cstr=parserString.cstr();
        !           218:                String *scontent_type=new(pool) String(pool, content_type);
        !           219:                Value *vcontent_type;
        !           220:                if(charset) {
        !           221:                        VHash *vhcontent_type=new(pool) VHash(pool);
        !           222:                        vhcontent_type->hash().put(*value_name, new(pool) VString(*scontent_type));
        !           223:                        String *scharset=new(pool) String(pool, charset);
        !           224:                        vhcontent_type->hash().put(*new(pool) String(pool, "charset"), new(pool) VString(*scharset));
        !           225:                        vcontent_type=vhcontent_type;
        !           226:                } else
        !           227:                        vcontent_type=new(pool) VString(*scontent_type);
        !           228:                vfile.set(false/*tainted*/, cstr, strlen(cstr), 0/*file_name*/, vcontent_type);
        !           229:                r.write_no_lang(vfile);
        !           230:        } catch(const XSLException& e) {
        !           231:                r._throw(&method_name, e);
        !           232:        }
        !           233: }
        !           234: 
        !           235: static void _set(Request& r, const String& method_name, MethodParams *params) {
        !           236:        Pool& pool=r.pool();
        !           237:        VXdoc& vdom=*static_cast<VXdoc *>(r.self);
        !           238: 
        !           239:        Value& vxml=params->as_junction(0, "xml must be code");
        !           240:        Temp_lang temp_lang(r, String::UL_XML);
        !           241:        const String& xml=r.process(vxml).as_string();
        !           242: 
        !           243:        std::istrstream stream(xml.cstr());
        !           244:        const XalanParsedSource* parsedSource;
        !           245:        int error=vdom.transformer().parseSource(&stream, parsedSource);
        !           246: 
        !           247:        if(error)
        !           248:                PTHROW(0, 0,
        !           249:                        &method_name,
        !           250:                        vdom.transformer().getLastError());
        !           251: 
        !           252:        // replace any previous parsed source
        !           253:        vdom.set_parsed_source(*parsedSource);
        !           254: }
        !           255: 
        !           256: static void _load(Request& r, const String& method_name, MethodParams *params) {
        !           257:        Pool& pool=r.pool();
        !           258:        VXdoc& vdom=*static_cast<VXdoc *>(r.self);
        !           259: 
        !           260:        // filespec
        !           261:        const String& file_name=params->as_string(0, "file name must not be code");
        !           262:        const char *filespec=r.absolute(file_name).cstr(String::UL_FILE_SPEC);
        !           263:        
        !           264:        const XalanParsedSource* parsedSource;
        !           265:        int error=vdom.transformer().parseSource(filespec, parsedSource);
        !           266: 
        !           267:        if(error)
        !           268:                PTHROW(0, 0,
        !           269:                        &file_name,
        !           270:                        vdom.transformer().getLastError());
        !           271: 
        !           272:        // replace any previous parsed source
        !           273:        vdom.set_parsed_source(*parsedSource);
        !           274: }
        !           275: 
        !           276: static void add_xslt_param(const Hash::Key& aattribute, Hash::Val *ameaning, 
        !           277:                                                   void *info) {
        !           278:        XalanTransformer& transformer=*static_cast<XalanTransformer *>(info);
        !           279:        const char *attribute_cstr=aattribute.cstr();
        !           280:        const char *meaning_cstr=static_cast<Value *>(ameaning)->as_string().cstr();
        !           281: 
        !           282:        transformer.setStylesheetParam(
        !           283:                XalanDOMString(attribute_cstr),  
        !           284:                XalanDOMString(meaning_cstr));
        !           285: }
        !           286: static void _xslt(Request& r, const String& method_name, MethodParams *params) {
        !           287:        Pool& pool=r.pool();
        !           288:        VXdoc& vdom=*static_cast<VXdoc *>(r.self);
        !           289: 
        !           290:        // params
        !           291:        if(params->size()>1) {
        !           292:                Value& vparams=params->as_no_junction(1, "transform parameters parameter must not be code");
        !           293:                if(vparams.is_defined())
        !           294:                        if(Hash *params=vparams.get_hash())
        !           295:                                params->for_each(add_xslt_param, &vdom.transformer());
        !           296:                        else
        !           297:                                PTHROW(0, 0,
        !           298:                                        &method_name,
        !           299:                                        "transform parameters parameter must be hash");
        !           300:        }
        !           301: 
        !           302:        // source
        !           303:        const XalanParsedSource &parsed_source=vdom.get_parsed_source(pool, &method_name);
        !           304: 
        !           305:        // stylesheet
        !           306:        const String& stylesheet_file_name=params->as_string(0, "file name must not be code");
        !           307:        const String& stylesheet_filespec=r.absolute(stylesheet_file_name);
        !           308:        //_asm int 3;
        !           309:        Stylesheet_connection& connection=XSLT_stylesheet_manager->get_connection(stylesheet_filespec);
        !           310: 
        !           311:        // target
        !           312:        XalanDocument* target=vdom.parser_liaison().createDocument();
        !           313:        XSLTResultTarget domResultTarget(target);
        !           314: 
        !           315:        // transform
        !           316:        int error=vdom.transformer().transform(
        !           317:                parsed_source, 
        !           318:                &connection.stylesheet(), 
        !           319:                domResultTarget);
        !           320:        connection.close();
        !           321:        if(error)
        !           322:                PTHROW(0, 0,
        !           323:                        &stylesheet_file_name,
        !           324:                        vdom.transformer().getLastError());
        !           325: 
        !           326:        // write out result
        !           327:        VXdoc& result=*new(pool) VXdoc(pool);
        !           328:        result.set_document(*target);
        !           329:        r.write_no_lang(result);
        !           330: }
        !           331: 
        !           332: // constructor
        !           333: 
        !           334: MXdoc::MXdoc(Pool& apool) : MXnode(apool) {
        !           335:        set_name(*NEW String(pool(), XDOC_CLASS_NAME));
        !           336: 
        !           337:        // ^dom.save[some.xml]
        !           338:        // ^dom.save[some.xml;options hash]
        !           339:        add_native_method("save", Method::CT_DYNAMIC, _save, 1, 2);
        !           340: 
        !           341:        // ^dom.string[] <doc/>
        !           342:        // ^dom.string[options hash] <doc/>
        !           343:        add_native_method("string", Method::CT_DYNAMIC, _string, 0, 1);
        !           344: 
        !           345:        // ^dom.file[] file with "<doc/>"
        !           346:        // ^dom.file[options hash] file with "<doc/>"
        !           347:        add_native_method("file", Method::CT_DYNAMIC, _file, 0, 1);
        !           348: 
        !           349:        // ^dom::set[<some>xml</some>]
        !           350:        add_native_method("set", Method::CT_DYNAMIC, _set, 1, 1);
        !           351: 
        !           352:        // ^dom::load[some.xml]
        !           353:        add_native_method("load", Method::CT_DYNAMIC, _load, 1, 1);
        !           354: 
        !           355:        // ^dom.xslt[stylesheet file_name]
        !           356:        // ^dom.xslt[stylesheet file_name;params hash]
        !           357:        add_native_method("xslt", Method::CT_DYNAMIC, _xslt, 1, 2);
        !           358: 
        !           359: }
        !           360: // global variable
        !           361: 
        !           362: Methoded *Xdoc_class;
        !           363: 
        !           364: // creator
        !           365: 
        !           366: #endif
        !           367: 
        !           368: Methoded *MXdoc_create(Pool& pool) {
        !           369:        return 
        !           370: #ifdef XML
        !           371:                Xdoc_class=new(pool) MXdoc(pool);
        !           372: #else
        !           373:                0
        !           374: #endif
        !           375:        ;
        !           376: }

E-mail: