Annotation of parser3/src/classes/xnode.C, revision 1.6

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: 
1.6     ! parser      7:        $Id: xnode.C,v 1.5 2001/10/11 14:58:15 parser Exp $
1.1       parser      8: */
                      9: #include "classes.h"
                     10: #ifdef XML
                     11: 
                     12: #include "pa_request.h"
                     13: #include "pa_vxnode.h"
                     14: 
                     15: #include "xnode.h"
                     16: 
                     17: #include <util/XMLString.hpp>
                     18: #include <XalanSourceTree/XalanSourceTreeDOMSupport.hpp>
                     19: #include <XPath/XPathEvaluator.hpp>
                     20: #include <XPath/NodeRefList.hpp>
1.6     ! parser     21: #include <XalanDOM/XalanElement.hpp>
        !            22: #include <XalanDOM/XalanAttr.hpp>
        !            23: #include <XalanDOM/XalanNodeList.hpp>
1.1       parser     24: 
                     25: // defines
                     26: 
                     27: #define XNODE_CLASS_NAME "xnode"
                     28: 
1.6     ! parser     29: // helpers
        !            30: 
        !            31: XalanNode& as_node(Pool& pool, const String& method_name, MethodParams *params, 
        !            32:                                                int index, const char *msg) {
        !            33:        Value& value=params->as_no_junction(index, msg);
        !            34:        if(strcmp(value.type(), VXNODE_TYPE)!=0)
        !            35:                PTHROW(0, 0,
        !            36:                        &method_name,
        !            37:                        msg);
        !            38: 
        !            39:        VXnode& vnode=*static_cast<VXnode *>(&value);
        !            40:        return vnode.get_node(pool, &method_name);
        !            41: }
        !            42: 
        !            43: // helpers
        !            44: 
        !            45: XalanAttr& as_attr(Pool& pool, const String& method_name, MethodParams *params, 
        !            46:                                                int index, const char *msg) {
        !            47:        XalanNode& node=as_node(pool, method_name, params, index, msg);
        !            48: 
        !            49:        if(node.getNodeType()!=XalanNode::ATTRIBUTE_NODE)
        !            50:                PTHROW(0, 0, 
        !            51:                        &method_name,
        !            52:                        msg);
        !            53: 
        !            54:        return *reinterpret_cast<XalanAttr *>(&node);
        !            55: }
1.1       parser     56: 
                     57: // methods
                     58: 
1.6     ! parser     59: // DOM1 node
        !            60: 
        !            61: // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException);
        !            62: static void _insertBefore(Request& r, const String& method_name, MethodParams *params) {
        !            63:        Pool& pool=r.pool();
        !            64:        VXnode& vnode=*static_cast<VXnode *>(r.self);
        !            65:        XalanNode& node=vnode.get_node(pool, &method_name);
        !            66: 
        !            67:        XalanNode& newChild=as_node(pool, method_name, params, 0, "newChild must be node");
        !            68:        XalanNode& refChild=as_node(pool, method_name, params, 1, "refChild must be node");
        !            69:        
        !            70:        try {
        !            71:                node.insertBefore(&newChild, &refChild);
        !            72:        } catch(const XalanDOMException& e)     {
        !            73:                pool.exception()._throw(pool, &method_name, e);
        !            74:        }
        !            75: }
        !            76: 
        !            77: // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException);
        !            78: static void _replaceChild(Request& r, const String& method_name, MethodParams *params) {
        !            79:        Pool& pool=r.pool();
        !            80:        VXnode& vnode=*static_cast<VXnode *>(r.self);
        !            81:        XalanNode& node=vnode.get_node(pool, &method_name);
        !            82: 
        !            83:        XalanNode& newChild=as_node(pool, method_name, params, 0, "newChild must be node");
        !            84:        XalanNode& refChild=as_node(pool, method_name, params, 1, "refChild must be node");
        !            85:        
        !            86:        try {
        !            87:                node.replaceChild(&newChild, &refChild);
        !            88:        } catch(const XalanDOMException& e)     {
        !            89:                pool.exception()._throw(pool, &method_name, e);
        !            90:        }
        !            91: }
        !            92: 
        !            93: // Node removeChild(in Node oldChild) raises(DOMException);
        !            94: static void _removeChild(Request& r, const String& method_name, MethodParams *params) {
        !            95:        Pool& pool=r.pool();
        !            96:        VXnode& vnode=*static_cast<VXnode *>(r.self);
        !            97:        XalanNode& node=vnode.get_node(pool, &method_name);
        !            98: 
        !            99:        XalanNode& oldChild=as_node(pool, method_name, params, 0, "oldChild must be node");
        !           100:        
        !           101:        try {
        !           102:                node.removeChild(&oldChild);
        !           103:        } catch(const XalanDOMException& e)     {
        !           104:                pool.exception()._throw(pool, &method_name, e);
        !           105:        }
        !           106: }
        !           107: 
        !           108: // Node appendChild(in Node newChild) raises(DOMException);
        !           109: static void _appendChild(Request& r, const String& method_name, MethodParams *params) {
        !           110:        Pool& pool=r.pool();
        !           111:        VXnode& vnode=*static_cast<VXnode *>(r.self);
        !           112:        XalanNode& node=vnode.get_node(pool, &method_name);
        !           113: 
        !           114:        XalanNode& newChild=as_node(pool, method_name, params, 0, "newChild must be node");
        !           115:        
        !           116:        try {
        !           117:                node.appendChild(&newChild);
        !           118:        } catch(const XalanDOMException& e)     {
        !           119:                pool.exception()._throw(pool, &method_name, e);
        !           120:        }
        !           121: }
        !           122: 
        !           123: // boolean hasChildNodes();
        !           124: static void _hasChildNodes(Request& r, const String& method_name, MethodParams *) {
        !           125:        Pool& pool=r.pool();
        !           126:        VXnode& vnode=*static_cast<VXnode *>(r.self);
        !           127:        XalanNode& node=vnode.get_node(pool, &method_name);
        !           128: 
        !           129:        // write out result
        !           130:        VBool& result=*new(pool) VBool(pool, node.hasChildNodes());
        !           131:        result.set_name(method_name);
        !           132:        r.write_no_lang(result);
        !           133: }
        !           134: 
        !           135: // Node cloneNode(in boolean deep);
        !           136: /// @test 1. who frees it up? 2. ownerDocument=?
        !           137: static void _cloneNode(Request& r, const String& method_name, MethodParams *params) {
        !           138:        Pool& pool=r.pool();
        !           139:        VXnode& vnode=*static_cast<VXnode *>(r.self);
        !           140:        XalanNode& node=vnode.get_node(pool, &method_name);
        !           141: 
        !           142:        bool deep=params->as_bool(0, "deep must be bool", r);
        !           143: 
        !           144:        // write out result
        !           145:        VXnode& result=*new(pool) VXnode(pool, node.cloneNode(deep));
        !           146:        result.set_name(method_name);
        !           147:        r.write_no_lang(result);
        !           148: }
        !           149: 
        !           150: // DOM1 element
        !           151: 
        !           152: XalanElement& get_self_element(Request& r, const String& method_name) {
        !           153:        Pool& pool=r.pool();
        !           154:        VXnode& vnode=*static_cast<VXnode *>(r.self);
        !           155:        XalanNode& node=vnode.get_node(pool, &method_name);
        !           156: 
        !           157:        if(node.getNodeType()!=XalanNode::ELEMENT_NODE)
        !           158:                PTHROW(0, 0, 
        !           159:                        &method_name,
        !           160:                        "method can be called on node of ELEMENT type");
        !           161: 
        !           162:        return *reinterpret_cast<XalanElement *>(&node);
        !           163: }
        !           164: 
        !           165: // DOMString getAttribute(in DOMString name);
        !           166: static void _getAttribute(Request& r, const String& method_name, MethodParams *params) {
        !           167:        Pool& pool=r.pool();
        !           168:        XalanElement& element=get_self_element(r, method_name);
        !           169:        const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS);
        !           170: 
        !           171:        const XalanDOMString& attribute_value=element.getAttribute(XalanDOMString(name));
        !           172:        // write out result
        !           173:        r.write_no_lang(*new(pool) VString(pool.transcode(attribute_value)));
        !           174: }
        !           175: 
        !           176: // void setAttribute(in DOMString name, in DOMString value) raises(DOMException);
        !           177: static void _setAttribute(Request& r, const String& method_name, MethodParams *params) {
        !           178:        Pool& pool=r.pool();
        !           179:        XalanElement& element=get_self_element(r, method_name);
        !           180:        const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS);
        !           181:        const char *attribute_value=params->as_string(1, "value must not be code").cstr(String::UL_AS_IS);
        !           182: 
        !           183:        try {
        !           184:                element.setAttribute(
        !           185:                        XalanDOMString(name), 
        !           186:                        XalanDOMString(attribute_value));
        !           187:        } catch(const XalanDOMException& e)     {
        !           188:                pool.exception()._throw(pool, &method_name, e);
        !           189:        }
        !           190: }
        !           191: 
        !           192: // void removeAttribute(in DOMString name) raises(DOMException);
        !           193: static void _removeAttribute(Request& r, const String& method_name, MethodParams *params) {
        !           194:        Pool& pool=r.pool();
        !           195:        XalanElement& element=get_self_element(r, method_name);
        !           196:        const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS);
        !           197: 
        !           198:        try {
        !           199:                element.removeAttribute(XalanDOMString(name));
        !           200:        } catch(const XalanDOMException& e)     {
        !           201:                pool.exception()._throw(pool, &method_name, e);
        !           202:        }
        !           203: }
        !           204: 
        !           205: // Attr getAttributeNode(in DOMString name);
        !           206: static void _getAttributeNode(Request& r, const String& method_name, MethodParams *params) {
        !           207:        Pool& pool=r.pool();
        !           208:        XalanElement& element=get_self_element(r, method_name);
        !           209:        const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS);
        !           210: 
        !           211:        if(XalanAttr *attr=element.getAttributeNode(XalanDOMString(name))) {
        !           212:                // write out result
        !           213:                VXnode& result=*new(pool) VXnode(pool, attr);
        !           214:                r.write_no_lang(result);
        !           215:        }
        !           216: }      
        !           217: 
        !           218: // Attr setAttributeNode(in Attr newAttr) raises(DOMException);
        !           219: static void _setAttributeNode(Request& r, const String& method_name, MethodParams *params) {
        !           220:        Pool& pool=r.pool();
        !           221:        XalanElement& element=get_self_element(r, method_name);
        !           222:        XalanAttr& newAttr=as_attr(pool, method_name, params, 0, "newAttr must be ATTRIBUTE node");
        !           223: 
        !           224:        try {
        !           225:                if(XalanAttr *returnAttr=element.setAttributeNode(&newAttr)) {
        !           226:                        // write out result
        !           227:                        VXnode& result=*new(pool) VXnode(pool, returnAttr);
        !           228:                        r.write_no_lang(result);
        !           229:                }
        !           230:        } catch(const XalanDOMException& e)     {
        !           231:                pool.exception()._throw(pool, &method_name, e);
        !           232:        }
        !           233: }      
        !           234: 
        !           235: // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException);
        !           236: static void _removeAttributeNode(Request& r, const String& method_name, MethodParams *params) {
        !           237:        Pool& pool=r.pool();
        !           238:        XalanElement& element=get_self_element(r, method_name);
        !           239:        XalanAttr& oldAttr=as_attr(pool, method_name, params, 0, "oldAttr must be ATTRIBUTE node");
        !           240: 
        !           241:        try {
        !           242:                if(XalanAttr *returnAttr=element.removeAttributeNode(&oldAttr)) {
        !           243:                        // write out result
        !           244:                        VXnode& result=*new(pool) VXnode(pool, returnAttr);
        !           245:                        r.write_no_lang(result);
        !           246:                }
        !           247:        } catch(const XalanDOMException& e)     {
        !           248:                pool.exception()._throw(pool, &method_name, e);
        !           249:        }
        !           250: }      
        !           251: 
        !           252: // NodeList getElementsByTagName(in DOMString name);
        !           253: static void _getElementsByTagName(Request& r, const String& method_name, MethodParams *params) {
        !           254:        Pool& pool=r.pool();
        !           255:        XalanElement& element=get_self_element(r, method_name);
        !           256: 
        !           257:        const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS);
        !           258: 
        !           259:        VHash& result=*new(pool) VHash(pool);
        !           260:        if(const XalanNodeList *nodes=
        !           261:                element.getElementsByTagName(XalanDOMString(name))) {
        !           262:                for(int i=0; i<nodes->getLength(); i++) {
        !           263:                        String& skey=*new(pool) String(pool);
        !           264:                        {
        !           265:                                char *buf=(char *)pool.malloc(MAX_NUMBER);
        !           266:                                snprintf(buf, MAX_NUMBER, "%d", i);
        !           267:                                skey << buf;
        !           268:                        }
        !           269: 
        !           270:                        result.hash().put(skey, new(pool) VXnode(pool, nodes->item(i)));
        !           271:                }
        !           272:        }
        !           273: 
        !           274:        // write out result
        !           275:        r.write_no_lang(result);
        !           276: }
        !           277: 
        !           278: // void normalize();
        !           279: static void _normalize(Request& r, const String& method_name, MethodParams *) {
        !           280:        XalanElement& element=get_self_element(r, method_name);
        !           281: 
        !           282:        element.normalize();
        !           283: }
        !           284: 
        !           285: 
1.1       parser    286: static void _select(Request& r, const String& method_name, MethodParams *params) {
                    287: //     _asm int 3;
                    288:        Pool& pool=r.pool();
                    289:        VXnode& vnode=*static_cast<VXnode *>(r.self);
                    290: 
                    291:        // expression
                    292:        const String& expression=params->as_string(0, "expression must not be code");
                    293:        const char *expression_cstr=expression.cstr(String::UL_AS_IS);
                    294:        XalanDOMString dstring(expression_cstr);
                    295:        const XalanDOMChar *expression_dcstr=dstring.c_str();
                    296: 
                    297:        XPathEvaluator evaluator;
                    298:        // We'll use these to parse the XML file.
                    299:        XalanSourceTreeDOMSupport dom_support;
                    300: 
                    301:        try {
                    302:                NodeRefList list=evaluator.selectNodeList(dom_support, 
                    303:                        &vnode.get_node(pool, &method_name), 
                    304:                        expression_dcstr);
                    305: 
                    306:                VHash& result=*new(pool) VHash(pool);
                    307:                for(int i=0; i<list.getLength(); i++) {
                    308:                        String& skey=*new(pool) String(pool);
                    309:                        {
                    310:                                char *buf=(char *)pool.malloc(MAX_NUMBER);
                    311:                                snprintf(buf, MAX_NUMBER, "%d", i);
                    312:                                skey << buf;
                    313:                        }
                    314: 
                    315:                        result.hash().put(skey, new(pool) VXnode(pool, list.item(i)));
                    316:                }
                    317:                result.set_name(method_name);
                    318:                r.write_no_lang(result);
                    319:        } catch(const XSLException& e) {
1.4       parser    320:                pool.exception()._throw(pool, &expression, e);
1.1       parser    321:        }
                    322: }
                    323: 
                    324: static void _select_single(Request& r, const String& method_name, MethodParams *params) {
                    325: //     _asm int 3;
                    326:        Pool& pool=r.pool();
                    327:        VXnode& vnode=*static_cast<VXnode *>(r.self);
                    328: 
                    329:        // expression
                    330:        const String& expression=params->as_string(0, "expression must not be code");
                    331:        const char *expression_cstr=expression.cstr(String::UL_AS_IS);
                    332:        XalanDOMString dstring(expression_cstr);
                    333:        const XalanDOMChar *expression_dcstr=dstring.c_str();
                    334: 
                    335:        XPathEvaluator evaluator;
                    336:        // Initialize the XalanSourceTree subsystem...
                    337: //     XalanSourceTreeInit             theSourceTreeInit;
                    338:        // We'll use these to parse the XML file.
                    339:        XalanSourceTreeDOMSupport dom_support;
                    340: 
                    341:        try {
                    342:                 if(XalanNode *node=evaluator.selectSingleNode(dom_support, 
                    343:                        &vnode.get_node(pool, &method_name), 
                    344:                        expression_dcstr)) {
                    345: 
                    346:                        VXnode& result=*new(pool) VXnode(pool, node);
                    347:                        result.set_name(method_name);
                    348:                        r.write_no_lang(result);
                    349:                }
                    350:        } catch(const XSLException& e) {
1.4       parser    351:                pool.exception()._throw(pool, &expression, e);
1.1       parser    352:        }
                    353: }
                    354: 
                    355: // constructor
                    356: 
1.2       parser    357: MXnode::MXnode(Pool& apool) : Methoded(apool), 
                    358:        consts(apool) {
1.1       parser    359:        set_name(*NEW String(pool(), XNODE_CLASS_NAME));
1.6     ! parser    360: 
        !           361:        /// DOM1 node
        !           362: 
        !           363:        // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException);
        !           364:        add_native_method("insertBefore", Method::CT_DYNAMIC, _insertBefore, 2, 2);
        !           365:        // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException);
        !           366:        add_native_method("replaceChild", Method::CT_DYNAMIC, _replaceChild, 2, 2);
        !           367:        // Node removeChild(in Node oldChild) raises(DOMException);
        !           368:        add_native_method("removeChild", Method::CT_DYNAMIC, _removeChild, 1, 1);
        !           369:        // Node appendChild(in Node newChild) raises(DOMException);
        !           370:        add_native_method("appendChild", Method::CT_DYNAMIC, _appendChild, 1, 1);
        !           371:        // boolean hasChildNodes();
        !           372:        add_native_method("hasChildNodes", Method::CT_DYNAMIC, _hasChildNodes, 0, 0);
        !           373:        // Node cloneNode(in boolean deep);
        !           374:        add_native_method("cloneNode", Method::CT_DYNAMIC, _cloneNode, 1, 1);
        !           375: 
        !           376:        /// DOM1 element
        !           377: 
        !           378:        // DOMString getAttribute(in DOMString name);
        !           379:        add_native_method("getAttribute", Method::CT_DYNAMIC, _getAttribute, 1, 1);
        !           380:        // void setAttribute(in DOMString name, in DOMString value) raises(DOMException);
        !           381:        add_native_method("setAttribute", Method::CT_DYNAMIC, _setAttribute, 2, 2);
        !           382:        // void removeAttribute(in DOMString name) raises(DOMException);
        !           383:        add_native_method("removeAttribute", Method::CT_DYNAMIC, _removeAttribute, 1, 1);
        !           384:        // Attr getAttributeNode(in DOMString name);
        !           385:        add_native_method("getAttributeNode", Method::CT_DYNAMIC, _getAttributeNode, 1, 1);
        !           386:        // Attr setAttributeNode(in Attr newAttr) raises(DOMException);
        !           387:        add_native_method("setAttributeNode", Method::CT_DYNAMIC, _setAttributeNode, 1, 1);
        !           388:        // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException);
        !           389:        add_native_method("removeAttributeNode", Method::CT_DYNAMIC, _removeAttributeNode, 1, 1);
        !           390:        // NodeList getElementsByTagName(in DOMString name);
        !           391:        add_native_method("getElementsByTagName", Method::CT_DYNAMIC, _getElementsByTagName, 1, 1);
        !           392:        // void normalize();
        !           393:        add_native_method("normalize", Method::CT_DYNAMIC, _normalize, 0, 0);
        !           394: 
        !           395:        /// parser
1.1       parser    396: 
                    397:        // ^node.select[/some/xpath/query] = hash $.#[dnode]
                    398:        add_native_method("select", Method::CT_DYNAMIC, _select, 1, 1);
                    399: 
1.5       parser    400:        // ^node.selectSingle[/some/xpath/query] = first dnode
                    401:        add_native_method("selectSingle", Method::CT_DYNAMIC, _select_single, 1, 1);
1.2       parser    402: 
                    403:        // consts
                    404: 
                    405: #define CONST(name, value) \
                    406:        consts.put(*new(pool()) String(pool(), #name), new(pool()) VInt(pool(), value))
                    407: 
                    408:        CONST(ELEMENT_NODE, 1);
                    409:     CONST(ATTRIBUTE_NODE,  2);
                    410:     CONST(TEXT_NODE,  3);
                    411:     CONST(CDATA_SECTION_NODE,  4);
                    412:     CONST(ENTITY_REFERENCE_NODE,  5);
                    413:     CONST(ENTITY_NODE,  6);
                    414:     CONST(PROCESSING_INSTRUCTION_NODE,  7);
                    415:     CONST(COMMENT_NODE,  8);
                    416:     CONST(DOCUMENT_NODE,  9);
                    417:     CONST(DOCUMENT_TYPE_NODE,  10);
                    418:     CONST(DOCUMENT_FRAGMENT_NODE,  11);
                    419:     CONST(NOTATION_NODE,  12);
1.1       parser    420: 
                    421: }
1.3       parser    422: 
1.1       parser    423: // global variable
                    424: 
                    425: Methoded *Xnode_class;
                    426: 
                    427: #endif
                    428: 
                    429: // creator
                    430: Methoded *MXnode_create(Pool& pool) {
                    431:        return 
                    432: #ifdef XML
                    433:                Xnode_class=new(pool) MXnode(pool)
                    434: #else
                    435:                0
                    436: #endif
                    437:                ;
                    438: }

E-mail: