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

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

E-mail: