Annotation of parser3/src/classes/dnode.C, revision 1.2

1.1       parser      1: /** @file
                      2:        Parser: @b dom parser class.
                      3: 
                      4:        Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
                      5: 
                      6:        Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
                      7: */
1.2     ! parser      8: static const char *RCSId="$Id: dnode.C,v 1.1 2001/09/18 12:25:06 parser Exp $"; 
1.1       parser      9: 
                     10: #if _MSC_VER
                     11: #      pragma warning(disable:4291)   // disable warning 
                     12: //     "no matching operator delete found; memory will not be freed if initialization throws an exception
                     13: #endif
                     14: 
                     15: #include "classes.h"
                     16: #include "pa_request.h"
                     17: #include "pa_vdnode.h"
1.2     ! parser     18: #include "pa_vfile.h"
        !            19: 
1.1       parser     20: #include "dnode.h"
                     21: 
                     22: #include <util/XMLString.hpp>
                     23: //#include <XalanSourceTree/XalanSourceTreeInit.hpp>
                     24: #include <XalanSourceTree/XalanSourceTreeDOMSupport.hpp>
                     25: #include <XPath/XPathEvaluator.hpp>
                     26: #include <XPath/NodeRefList.hpp>
1.2     ! parser     27: #include <XMLSupport/FormatterToXML.hpp>
        !            28: #include <XMLSupport/FormatterToHTML.hpp>
        !            29: #include <XMLSupport/FormatterToText.hpp>
        !            30: #include <XMLSupport/FormatterTreeWalker.hpp>
        !            31: #include <PlatformSupport/XalanFileOutputStream.hpp>
        !            32: #include <PlatformSupport/XalanOutputStreamPrintWriter.hpp>
        !            33: #include <PlatformSupport/DOMStringPrintWriter.hpp>
1.1       parser     34: 
                     35: // defines
                     36: 
                     37: #define DNODE_CLASS_NAME "dnode"
                     38: 
1.2     ! parser     39: #define DOM_OUTPUT_METHOD_OPTION_NAME "method"
        !            40: #define DOM_OUTPUT_METHOD_OPTION_VALUE_XML "xml"
        !            41: #define DOM_OUTPUT_METHOD_OPTION_VALUE_HTML "html"
        !            42: #define DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT "text"
        !            43: 
        !            44: #define DOM_OUTPUT_ENCODING_OPTION_NAME "encoding"
        !            45: 
        !            46: #define DOM_OUTPUT_DEFAULT_INDENT 4
        !            47: 
1.1       parser     48: // class
                     49: 
                     50: // methods
                     51: 
1.2     ! parser     52: class ParserStringXalanOutputStream: public XalanOutputStream {
        !            53: public:
        !            54:        
        !            55:        explicit ParserStringXalanOutputStream(String& astring) : fstring(astring) {}
        !            56: 
        !            57: protected: // XalanOutputStream
        !            58: 
        !            59:        virtual void writeData(const char *theBuffer, unsigned long theBufferLength) {
        !            60:                char *copy=(char *)fstring.malloc((size_t)theBufferLength);
        !            61:                memcpy(copy, theBuffer, (size_t)theBufferLength);
        !            62:                fstring.APPEND_CLEAN(copy, (size_t)theBufferLength, "dom", -1);
        !            63:        }
        !            64: 
        !            65:        virtual void doFlush() {}
        !            66: 
        !            67: private:
        !            68: 
        !            69:        String& fstring;
        !            70:        
        !            71: };
        !            72: 
        !            73: static void create_optioned_listener(
        !            74:                                                                         const char *& content_type, const char *& charset, FormatterListener *& listener, 
        !            75:                                                                         Pool& pool, 
        !            76:                                                                         const String& method_name, MethodParams *params, int index, Writer& writer) {
        !            77:        charset=0;
        !            78:        const String *method=0;
        !            79:        XalanDOMString xalan_encoding;
        !            80: 
        !            81:        Value& voptions=params->as_no_junction(index, "options must not be code");
        !            82:        if(voptions.is_defined()) {
        !            83:                if(Hash *options=voptions.get_hash()) {
        !            84:                        // $.method[xml|html|text]
        !            85:                        if(Value *vmethod=static_cast<Value *>(options->get(*new(pool) 
        !            86:                                String(pool, DOM_OUTPUT_METHOD_OPTION_NAME))))
        !            87:                                method=&vmethod->as_string();
        !            88: 
        !            89:                        // $.encoding[windows-1251|...]
        !            90:                        if(Value *vencoding=static_cast<Value *>(options->get(*new(pool) 
        !            91:                                String(pool, DOM_OUTPUT_ENCODING_OPTION_NAME)))) {
        !            92:                                charset=vencoding->as_string().cstr();
        !            93:                                xalan_encoding.append(charset, strlen(charset));
        !            94:                        }
        !            95:                } else
        !            96:                        PTHROW(0, 0,
        !            97:                                &method_name,
        !            98:                                "options must be hash");
        !            99:        }
        !           100: 
        !           101:        if(!method/*default='xml'*/ || *method == DOM_OUTPUT_METHOD_OPTION_VALUE_XML) {
        !           102:                content_type="text/xml";
        !           103:                listener=new FormatterToXML(writer,
        !           104:                        XalanDOMString(),  // version
        !           105:                        true, // doIndent
        !           106:                        DOM_OUTPUT_DEFAULT_INDENT, // indent 
        !           107:                        xalan_encoding  // encoding
        !           108:                );
        !           109:        } else if(*method == DOM_OUTPUT_METHOD_OPTION_VALUE_HTML) {
        !           110:                content_type="text/html";
        !           111:                listener=new FormatterToHTML(writer,
        !           112:                        xalan_encoding,  // encoding
        !           113:                        XalanDOMString(),  // mediaType 
        !           114:                        XalanDOMString(),  // doctypeSystem; String to be printed at the top of the document 
        !           115:                        XalanDOMString(),  // doctypePublic  
        !           116:                        true, // doIndent 
        !           117:                        DOM_OUTPUT_DEFAULT_INDENT // indent 
        !           118:                );
        !           119:        } else if(*method == DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT) {
        !           120:                content_type="text/plain";
        !           121:                listener=new FormatterToText(writer,
        !           122:                        xalan_encoding  // encoding
        !           123:                );
        !           124:        } else
        !           125:                PTHROW(0, 0,
        !           126:                        method,
        !           127:                        DOM_OUTPUT_METHOD_OPTION_NAME " option is invalid; valid methods are: "
        !           128:                                "'" DOM_OUTPUT_METHOD_OPTION_VALUE_XML "', "
        !           129:                                "'" DOM_OUTPUT_METHOD_OPTION_VALUE_HTML "', "
        !           130:                                "'" DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT "'");                   
        !           131: 
        !           132:        // never reached
        !           133: }
        !           134: 
        !           135: static void _save(Request& r, const String& method_name, MethodParams *params) {
        !           136:        Pool& pool=r.pool();
        !           137:        VDnode& vnode=*static_cast<VDnode *>(r.self);
        !           138: 
        !           139:        // filespec
        !           140:        const String& file_name=params->as_string(1, "file name must not be code");
        !           141:        const char *filespec=r.absolute(file_name).cstr(String::UL_FILE_SPEC);
        !           142:        
        !           143:        // node
        !           144:        XalanNode& node=vnode.get_node(pool, &method_name);
        !           145: 
        !           146:        try {
        !           147:                XalanFileOutputStream stream(XalanDOMString(filespec, strlen(filespec)));
        !           148:                XalanOutputStreamPrintWriter writer(stream);
        !           149:                const char *content_type, *charset;
        !           150:                FormatterListener *formatterListener;
        !           151:                create_optioned_listener(content_type, charset, formatterListener, 
        !           152:                        pool, method_name, params, 0, writer);
        !           153:                FormatterTreeWalker treeWalker(*formatterListener);
        !           154:                treeWalker.traverse(&node); // Walk that node and produce the XML...
        !           155:        } catch(const XSLException& e) {
        !           156:                _throw(pool, &method_name, e);
        !           157:        }
        !           158: }
        !           159: 
        !           160: static void _string(Request& r, const String& method_name, MethodParams *params) {
        !           161:        Pool& pool=r.pool();
        !           162:        VDnode& vnode=*static_cast<VDnode *>(r.self);
        !           163: 
        !           164:        // node
        !           165:        XalanNode& node=vnode.get_node(pool, &method_name);
        !           166: 
        !           167:        try {
        !           168:                String parserString=*new(pool) String(pool);
        !           169:                ParserStringXalanOutputStream stream(parserString);
        !           170:                XalanOutputStreamPrintWriter writer(stream);
        !           171:                const char *content_type, *charset;
        !           172:                FormatterListener *formatterListener;
        !           173:                create_optioned_listener(content_type, charset, formatterListener, 
        !           174:                        pool, method_name, params, 0, writer);
        !           175:                FormatterTreeWalker treeWalker(*formatterListener);
        !           176:                treeWalker.traverse(&node); // Walk that node and produce the XML...
        !           177: 
        !           178:                // write out result
        !           179:                r.write_no_lang(parserString);
        !           180:        } catch(const XSLException& e) {
        !           181:                _throw(pool, &method_name, e);
        !           182:        }
        !           183: }
        !           184: 
        !           185: 
        !           186: static void _file(Request& r, const String& method_name, MethodParams *params) {
        !           187:        Pool& pool=r.pool();
        !           188:        VDnode& vnode=*static_cast<VDnode *>(r.self);
        !           189: 
        !           190:        // node
        !           191:        XalanNode& node=vnode.get_node(pool, &method_name);
        !           192: 
        !           193:        try {
        !           194:                String& parserString=*new(pool) String(pool);
        !           195:                ParserStringXalanOutputStream stream(parserString);
        !           196:                XalanOutputStreamPrintWriter writer(stream);
        !           197:                const char *content_type, *charset;
        !           198:                FormatterListener *formatterListener;
        !           199:                create_optioned_listener(content_type, charset, formatterListener, 
        !           200:                        pool, method_name, params, 0, writer);
        !           201:                FormatterTreeWalker treeWalker(*formatterListener);
        !           202:                treeWalker.traverse(&node); // Walk that node and produce the XML...
        !           203: 
        !           204:                // write out result
        !           205:                VFile& vfile=*new(pool) VFile(pool);
        !           206:                const char *cstr=parserString.cstr();
        !           207:                String *scontent_type=new(pool) String(pool, content_type);
        !           208:                Value *vcontent_type;
        !           209:                if(charset) {
        !           210:                        VHash *vhcontent_type=new(pool) VHash(pool);
        !           211:                        vhcontent_type->hash().put(*value_name, new(pool) VString(*scontent_type));
        !           212:                        String *scharset=new(pool) String(pool, charset);
        !           213:                        vhcontent_type->hash().put(*new(pool) String(pool, "charset"), new(pool) VString(*scharset));
        !           214:                        vcontent_type=vhcontent_type;
        !           215:                } else
        !           216:                        vcontent_type=new(pool) VString(*scontent_type);
        !           217:                vfile.set(false/*tainted*/, cstr, strlen(cstr), 0/*file_name*/, vcontent_type);
        !           218:                r.write_no_lang(vfile);
        !           219:        } catch(const XSLException& e) {
        !           220:                _throw(pool, &method_name, e);
        !           221:        }
        !           222: }
        !           223: 
        !           224: 
1.1       parser    225: static void _xpath(Request& r, const String& method_name, MethodParams *params) {
                    226: //     _asm int 3;
                    227:        Pool& pool=r.pool();
1.2     ! parser    228:        VDnode& vnode=*static_cast<VDnode *>(r.self);
1.1       parser    229: 
                    230:        // expression
                    231:        const String& expression=params->as_string(0, "expression must not be code");
                    232:        const char *expression_cstr=expression.cstr(String::UL_AS_IS);
                    233:        XalanDOMString dstring(expression_cstr);
                    234:        const XalanDOMChar *expression_dcstr=dstring.c_str();
                    235: 
                    236:        XPathEvaluator evaluator;
                    237:        // Initialize the XalanSourceTree subsystem...
                    238: //     XalanSourceTreeInit             theSourceTreeInit;
                    239:        // We'll use these to parse the XML file.
                    240:        XalanSourceTreeDOMSupport dom_support;
                    241: 
                    242:        try {
                    243:                NodeRefList list=evaluator.selectNodeList(dom_support, 
1.2     ! parser    244:                        &vnode.get_node(pool, &method_name), 
1.1       parser    245:                        expression_dcstr);
                    246: 
                    247:                VHash& result=*new(pool) VHash(pool);
                    248:                for(int i=0; i<list.getLength(); i++) {
                    249:                        String& skey=*new(pool) String(pool);
                    250:                        {
                    251:                                char *buf=(char *)pool.malloc(MAX_NUMBER);
                    252:                                snprintf(buf, MAX_NUMBER, "%d", i);
                    253:                                skey << buf;
                    254:                        }
                    255: 
                    256:                        result.hash().put(skey, new(pool) VDnode(pool, list.item(i)));
                    257:                }
                    258:                result.set_name(method_name);
                    259:                r.write_no_lang(result);
                    260:        } catch(const XSLException& e) {
                    261:                _throw(pool, &expression, e);
                    262:        }
                    263: }
                    264: 
                    265: // constructor
                    266: 
                    267: MDnode::MDnode(Pool& apool) : Methoded(apool) {
                    268:        set_name(*NEW String(pool(), DNODE_CLASS_NAME));
1.2     ! parser    269: 
        !           270:        // ^node.save[options hash;some.xml]
        !           271:        add_native_method("save", Method::CT_DYNAMIC, _save, 2, 2);
        !           272: 
        !           273:        // ^node.string[options hash] <doc/>
        !           274:        add_native_method("string", Method::CT_DYNAMIC, _string, 1, 1);
        !           275: 
        !           276:        // ^node.file[options hash] file with "<doc/>"
        !           277:        add_native_method("file", Method::CT_DYNAMIC, _file, 1, 1);
1.1       parser    278: 
                    279:        // ^node.xpath[/some/xpath/query]
                    280:        add_native_method("xpath", Method::CT_DYNAMIC, _xpath, 1, 1);
                    281: 
                    282: }
                    283: // global variable
                    284: 
                    285: Methoded *Dnode_class;
                    286: 
                    287: // creator
                    288: 
                    289: Methoded *MDnode_create(Pool& pool) {
                    290:        return Dnode_class=new(pool) MDnode(pool);
                    291: }

E-mail: