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

1.1       parser      1: /** @file
                      2:        Parser: @b dom parser class.
                      3: 
1.87      moko        4:        Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com)
1.38      paf         5:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.1       parser      6: */
                      7: #include "classes.h"
                      8: #ifdef XML
1.46      paf         9: 
1.56      paf        10: #include "pa_vmethod_frame.h"
1.1       parser     11: 
1.21      paf        12: #include "pa_charset.h"
1.1       parser     13: #include "pa_request.h"
                     14: #include "pa_vxnode.h"
1.34      paf        15: #include "pa_vxdoc.h"
1.23      paf        16: #include "pa_vvoid.h"
1.60      paf        17: #include "pa_xml_exception.h"
1.76      misha      18: #include "pa_vbool.h"
1.1       parser     19: 
                     20: #include "xnode.h"
1.21      paf        21: #include "libxml/xpath.h"
1.66      paf        22: #include "libxml/xpathInternals.h"
1.21      paf        23: 
1.88    ! moko       24: volatile const char * IDENT_XNODE_C="$Id: xnode.C,v 1.87 2012/03/16 09:24:08 moko Exp $" IDENT_XNODE_H;
1.87      moko       25: 
1.56      paf        26: // global variable
                     27: 
                     28: DECLARE_CLASS_VAR(xnode, new MXnode, 0);
                     29: 
1.21      paf        30: // classes
                     31: 
                     32: class xmlXPathObject_auto_ptr {
                     33: public:
1.29      paf        34:        explicit xmlXPathObject_auto_ptr(xmlXPathObject *_APtr = 0) 
                     35:                : _Owns(_APtr != 0), _Ptr(_APtr) {}
1.21      paf        36:        xmlXPathObject_auto_ptr(const xmlXPathObject_auto_ptr& _Y) 
                     37:                : _Owns(_Y._Owns), _Ptr(_Y.release()) {}
                     38:        xmlXPathObject_auto_ptr& operator=(const xmlXPathObject_auto_ptr& _Y) 
                     39:                {if (this != &_Y)
                     40:                        {if (_Ptr != _Y.get())
                     41:                                {if (_Owns && _Ptr)
                     42:                                        xmlXPathFreeObject(_Ptr);
                     43:                                _Owns = _Y._Owns; }
                     44:                        else if (_Y._Owns)
                     45:                                _Owns = true;
                     46:                        _Ptr = _Y.release(); }
                     47:                return (*this); }
                     48:        ~xmlXPathObject_auto_ptr()
                     49:                {if (_Owns && _Ptr)
                     50:                        xmlXPathFreeObject(_Ptr); }
                     51:        xmlXPathObject& operator*() const 
                     52:                {return (*get()); }
                     53:        xmlXPathObject *operator->() const 
                     54:                {return (get()); }
                     55:        xmlXPathObject *get() const 
                     56:                {return (_Ptr); }
                     57:        xmlXPathObject *release() const 
                     58:                {((xmlXPathObject_auto_ptr *)this)->_Owns = false;
                     59:                return (_Ptr); }
                     60: private:
                     61:        bool _Owns;
                     62:        xmlXPathObject *_Ptr;
                     63: };
                     64: 
                     65: class xmlXPathContext_auto_ptr {
                     66: public:
1.29      paf        67:        explicit xmlXPathContext_auto_ptr(xmlXPathContext *_APtr = 0) 
                     68:                : _Owns(_APtr != 0), _Ptr(_APtr) {}
1.21      paf        69:        xmlXPathContext_auto_ptr(const xmlXPathContext_auto_ptr& _Y) 
                     70:                : _Owns(_Y._Owns), _Ptr(_Y.release()) {}
                     71:        xmlXPathContext_auto_ptr& operator=(const xmlXPathContext_auto_ptr& _Y) 
                     72:                {if (this != &_Y)
                     73:                        {if (_Ptr != _Y.get())
                     74:                                {if (_Owns && _Ptr)
                     75:                                        xmlXPathFreeContext(_Ptr);
                     76:                                _Owns = _Y._Owns; }
                     77:                        else if (_Y._Owns)
                     78:                                _Owns = true;
                     79:                        _Ptr = _Y.release(); }
                     80:                return (*this); }
                     81:        ~xmlXPathContext_auto_ptr()
                     82:                {if (_Owns && _Ptr)
                     83:                        xmlXPathFreeContext(_Ptr); }
                     84:        xmlXPathContext& operator*() const 
                     85:                {return (*get()); }
                     86:        xmlXPathContext *operator->() const 
                     87:                {return (get()); }
                     88:        xmlXPathContext *get() const 
                     89:                {return (_Ptr); }
                     90:        xmlXPathContext *release() const 
                     91:                {((xmlXPathContext_auto_ptr *)this)->_Owns = false;
                     92:                return (_Ptr); }
                     93: private:
                     94:        bool _Owns;
                     95:        xmlXPathContext *_Ptr;
                     96: };
1.1       parser     97: 
1.6       parser     98: // helpers
                     99: 
1.72      paf       100: xmlNode& as_node(MethodParams& params, int index, const char* msg) {
1.56      paf       101:        Value& value=params.as_no_junction(index, msg);
1.84      misha     102:        if(Value* vxnode=value.as(VXNODE_TYPE))
1.72      paf       103:                return static_cast<VXnode*>(vxnode)->get_xmlnode();
                    104:        else
1.77      misha     105:                throw Exception(PARSER_RUNTIME,
1.56      paf       106:                        0,
1.6       parser    107:                        msg);
1.72      paf       108: }
1.56      paf       109: 
1.72      paf       110: xmlChar* as_xmlchar(Request& r, MethodParams& params, int index, const char* msg) {
                    111:        return r.transcode(params.as_string(index, msg));
1.6       parser    112: }
                    113: 
1.85      misha     114: xmlChar* as_xmlqname(Request& r, MethodParams& params, int index, const char* msg) {
                    115:        xmlChar* qname=r.transcode(params.as_string(index, msg ? msg : XML_QUALIFIED_NAME_MUST_BE_STRING));
                    116:        if(xmlValidateQName(qname, 0))
                    117:                throw XmlException(0, XML_INVALID_QUALIFIED_NAME, qname);
                    118:        return qname;
                    119: }
                    120: 
                    121: xmlChar* as_xmlncname(Request& r, MethodParams& params, int index, const char* msg) {
                    122:        xmlChar* ncname=r.transcode(params.as_string(index, msg ? msg : XML_NC_NAME_MUST_BE_STRING));
                    123:        if(xmlValidateNCName(ncname, 0))
                    124:                throw XmlException(0, XML_INVALID_NC_NAME, ncname);
                    125:        return ncname;
                    126: }
                    127: 
                    128: xmlChar* as_xmlname(Request& r, MethodParams& params, int index, const char* msg) {
                    129:        xmlChar* localName=r.transcode(params.as_string(index, msg ? msg : XML_LOCAL_NAME_MUST_BE_STRING));
                    130:        if(xmlValidateName(localName, 0))
                    131:                throw XmlException(0, XML_INVALID_LOCAL_NAME, localName);
                    132:        return localName;
                    133: }
                    134: 
                    135: xmlChar* as_xmlnsuri(Request& r, MethodParams& params, int index) {
                    136:        return r.transcode(params.as_string(index, XML_NAMESPACEURI_MUST_BE_STRING));
                    137: }
                    138: 
1.72      paf       139: xmlAttr& as_attr(MethodParams& params, int index, const char* msg) {
                    140:        xmlNode& xmlnode=as_node(params, index, msg);
                    141:        if(xmlnode.type!=XML_ATTRIBUTE_NODE)
1.77      misha     142:                throw Exception(PARSER_RUNTIME,
1.56      paf       143:                        0,
1.6       parser    144:                        msg);
                    145: 
1.72      paf       146:        return *(xmlAttr*)&xmlnode;
                    147: }
                    148: 
                    149: static void writeNode(Request& r, VXdoc& xdoc, xmlNode* node) {
1.73      paf       150:        if(!node|| xmlHaveGenericErrors())
1.88    ! moko      151:                throw XmlException(0, r); // OOM, bad name, things like that
1.72      paf       152: 
                    153:        // write out result
                    154:        r.write_no_lang(xdoc.wrap(*node));
                    155: }
                    156: 
                    157: static xmlNode* pa_getAttributeNodeNS(xmlNode& selfNode, 
                    158:                                                                          const xmlChar* localName,
                    159:                                                                          const xmlChar* namespaceURI) 
                    160: {
                    161:        for(xmlNode* currentNode=(xmlNode*)selfNode.properties;
                    162:                currentNode;
                    163:                currentNode=currentNode->next)
                    164:        {
                    165:                if(!namespaceURI || currentNode->ns && xmlStrEqual(currentNode->ns->href, namespaceURI))
                    166:                        if(!localName || xmlStrEqual(currentNode->name, localName))
                    167:                                return currentNode;
                    168:        }
                    169:        return 0;
                    170: }
                    171: 
                    172: xmlNs& pa_xmlMapNs(xmlDoc& doc, const xmlChar *href, const xmlChar *prefix) {
                    173:        assert(href);
                    174:        // prefix can be null
                    175: 
                    176:        xmlNs *cur=doc.oldNs;
                    177:        while (cur != NULL &&
                    178:                                 ((cur->prefix == NULL && prefix != NULL) ||
                    179:                                        (cur->prefix != NULL && prefix == NULL) ||
                    180:                                        !xmlStrEqual (cur->prefix, prefix)) &&
                    181:                                 !xmlStrEqual (cur->href, href))
                    182:                cur = cur->next;
                    183: 
                    184:        if (cur == NULL) {
                    185:                cur = xmlNewNs (NULL, href, prefix);
                    186:                if(!cur || xmlHaveGenericErrors())
1.88    ! moko      187:                        throw XmlException();
1.72      paf       188:                cur->next = doc.oldNs;
                    189:                doc.oldNs = cur;
                    190:        }
                    191: 
                    192:        return *cur;
                    193: }
                    194: 
1.82      misha     195: /// @todo: проверить, обновляется ли parent!
1.72      paf       196: static void pa_addAttributeNode(xmlNode& selfNode, xmlAttr& attrNode) 
                    197: {
                    198:        if(attrNode.type!=XML_ATTRIBUTE_NODE)
1.77      misha     199:                throw Exception(PARSER_RUNTIME,
1.72      paf       200:                        0,
                    201:                        "must be ATTRIBUTE_NODE");
                    202: 
                    203:     /*
                    204:      * Add it at the end to preserve parsing order ...
                    205:      */
                    206:     if (selfNode.properties == NULL) {
                    207:         selfNode.properties = &attrNode;
                    208:     } else {
                    209:         xmlAttrPtr prev = selfNode.properties;
                    210: 
                    211:         while (prev->next != NULL)
                    212:             prev = prev->next;
                    213:         prev->next = &attrNode;
                    214:         attrNode.prev = prev;
                    215:     }
                    216: 
                    217:     if (xmlIsID(selfNode.doc, &selfNode, &attrNode) == 1)
                    218:         xmlAddID(NULL, selfNode.doc, xmlNodeGetContent((xmlNode*)&attrNode), &attrNode);
                    219: }
                    220: 
                    221: static const xmlChar *
                    222: pa_xmlGetNsURI(xmlNode *node) {
                    223:        if (node == NULL || node->ns == NULL)
                    224:                return NULL;
                    225: 
                    226:        return node->ns->href;
                    227: }
                    228: 
                    229: #ifndef DOXYGEN
                    230: struct AccumulateFoundInfo
                    231: {
                    232:        HashStringValue* hash;
                    233:        VXdoc* vdoc;
                    234:        int index;
                    235: };
                    236: #endif
                    237: static void AccumulateFound(xmlNode& node, AccumulateFoundInfo* info)
                    238: {
                    239:        info->hash->put(
                    240:                String::Body::Format(info->index++), 
                    241:                &info->vdoc->wrap(node));
                    242: }
                    243: template<typename I> static void
                    244: pa_xmlNamedPreorderTraversal (
                    245:                                                          xmlNode *root, 
                    246:                                                          xmlChar *tagURI, 
                    247:                                                          xmlChar *tagName, 
                    248:                                                          void callback(xmlNode& node, I info),
                    249:                                                          I info) 
                    250: {
                    251:        for(xmlNode *iter=root->children; iter; iter = iter->next) {
                    252:                if(iter->type == XML_ELEMENT_NODE &&
                    253:                        (xmlStrEqual(iter->name, tagName) ||
                    254:                        xmlStrEqual(tagName, (const xmlChar*)"*"))) {
                    255:                                if(tagURI != NULL &&
                    256:                                        (xmlStrEqual(pa_xmlGetNsURI(iter), tagURI) ||
                    257:                                        xmlStrEqual(tagURI, (const xmlChar*)"*")))
                    258:                                        callback(*iter, info);
                    259:                                else if(tagURI == NULL)
                    260:                                        callback(*iter, info);
                    261:                        }
                    262:                        pa_xmlNamedPreorderTraversal(iter, tagURI, tagName, callback, info);
                    263:        }
                    264: 
                    265:        return;
1.6       parser    266: }
1.1       parser    267: 
1.72      paf       268: 
1.1       parser    269: // methods
                    270: 
1.6       parser    271: // DOM1 node
                    272: 
                    273: // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException);
1.56      paf       274: static void _insertBefore(Request& r, MethodParams& params) {
1.86      misha     275:        xmlNode& newChild=as_node(params, 0, "newChild must be node");
                    276:        xmlNode& refChild=as_node(params, 1, "refChild must be node");
                    277: 
1.56      paf       278:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       279:        VXdoc& vxdoc=vnode.get_vxdoc();
                    280: 
                    281:        //xmlNode& selfNode=vnode.get_xmlnode();
1.6       parser    282:        
1.72      paf       283:        xmlNode* retNode=xmlAddPrevSibling(&refChild, &newChild);
                    284:        // write out result
                    285:        writeNode(r, vxdoc, retNode);
1.6       parser    286: }
                    287: 
                    288: // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException);
1.56      paf       289: static void _replaceChild(Request& r, MethodParams& params) {
1.86      misha     290:        xmlNode& newChild=as_node(params, 0, "newChild must be node");
                    291:        xmlNode& oldChild=as_node(params, 1, "oldChild must be node");
                    292: 
1.56      paf       293:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       294:        VXdoc& vxdoc=vnode.get_vxdoc();
                    295:        xmlDoc& xmldoc=vxdoc.get_xmldoc();
                    296:        xmlNode& selfNode=vnode.get_xmlnode();
                    297: 
                    298:        if(newChild.doc!=&xmldoc)
1.74      paf       299:                throw Exception("xml.dom",
1.72      paf       300:                        0,
                    301:                        "WRONG_DOCUMENT_ERR");
                    302:        if(oldChild.doc!=&xmldoc)
1.74      paf       303:                throw Exception("xml.dom",
1.72      paf       304:                        0,
                    305:                        "WRONG_DOCUMENT_ERR");
                    306: 
1.74      paf       307:        if(oldChild.parent!=&selfNode)
                    308:                throw Exception("xml.dom",
                    309:                        0,
                    310:                        "NOT_FOUND_ERR");
                    311: 
1.72      paf       312:        xmlNode* refChild=oldChild.next;
                    313:        xmlUnlinkNode(&oldChild);
                    314:        xmlNode* retNode;
                    315:        if(refChild)
                    316:                retNode=xmlAddPrevSibling(refChild, &newChild);
                    317:        else
                    318:                retNode=xmlAddChild(&selfNode, &newChild);
                    319: 
                    320:        // write out result
                    321:        writeNode(r, vxdoc, retNode);
1.6       parser    322: }
                    323: 
                    324: // Node removeChild(in Node oldChild) raises(DOMException);
1.56      paf       325: static void _removeChild(Request& r, MethodParams& params) {
1.86      misha     326:        xmlNode& oldChild=as_node(params, 0, "refChild must be node");
                    327: 
1.56      paf       328:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       329:        VXdoc& vxdoc=vnode.get_vxdoc();
                    330:        xmlDoc& xmldoc=vxdoc.get_xmldoc();
                    331: //     xmlNode& selfNode=vnode.get_xmlnode();
1.6       parser    332:        
1.72      paf       333:        if(oldChild.doc!=&xmldoc)
1.74      paf       334:                throw Exception("xml.dom",
1.72      paf       335:                        0,
                    336:                        "WRONG_DOCUMENT_ERR");
                    337: 
                    338:        xmlUnlinkNode(&oldChild);
                    339:        // write out result
                    340:        writeNode(r, vxdoc, &oldChild);
1.6       parser    341: }
                    342: 
                    343: // Node appendChild(in Node newChild) raises(DOMException);
1.56      paf       344: static void _appendChild(Request& r, MethodParams& params) {
1.86      misha     345:        xmlNode& newChild=as_node(params, 0, "newChild must be node");
                    346: 
1.56      paf       347:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       348:        VXdoc& vxdoc=vnode.get_vxdoc();
                    349:        xmlNode& selfNode=vnode.get_xmlnode();
1.6       parser    350:        
1.72      paf       351:        xmlNode* retNode=xmlAddChild(&selfNode, &newChild);
                    352:        // write out result
                    353:        writeNode(r, vxdoc, retNode);
1.6       parser    354: }
                    355: 
                    356: // boolean hasChildNodes();
1.56      paf       357: static void _hasChildNodes(Request& r, MethodParams&) {
                    358:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       359:        xmlNode& node=vnode.get_xmlnode();
1.6       parser    360: 
                    361:        // write out result
1.83      misha     362:        r.write_no_lang(VBool::get(node.children!=0));
1.6       parser    363: }
                    364: 
                    365: // Node cloneNode(in boolean deep);
1.56      paf       366: static void _cloneNode(Request& r, MethodParams& params) {
1.86      misha     367:        bool deep=params.as_bool(0, "deep must be bool", r);
                    368: 
1.56      paf       369:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       370:        xmlNode& selfNode=vnode.get_xmlnode();
                    371:        VXdoc& vxdoc=vnode.get_vxdoc();
                    372:        xmlDoc& xmldoc=vxdoc.get_xmldoc();
1.6       parser    373: 
1.72      paf       374:        xmlNode* retNode=xmlDocCopyNode(&selfNode, &xmldoc, deep?1: 0);
1.6       parser    375:        // write out result
1.72      paf       376:        writeNode(r, vxdoc, retNode);
1.6       parser    377: }
                    378: 
                    379: // DOM1 element
                    380: 
1.72      paf       381: xmlNode& get_self_element(VXnode& vnode) {
                    382:        xmlNode& node=vnode.get_xmlnode();
1.6       parser    383: 
1.72      paf       384:        if(node.type!=XML_ELEMENT_NODE)
1.77      misha     385:                throw Exception(PARSER_RUNTIME,
1.56      paf       386:                        0,
1.51      paf       387:                        "method can only be called on nodes of ELEMENT type");
1.6       parser    388: 
1.72      paf       389:        return node;
1.6       parser    390: }
                    391: 
1.86      misha     392: // DOMString getAttribute(in DOMString name);
                    393: static void _getAttribute(Request& r, MethodParams& params) {
                    394:        const xmlChar* name=as_xmlname(r, params, 0);
1.56      paf       395: 
1.67      paf       396:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       397:        xmlNode& element=get_self_element(vnode);
1.6       parser    398: 
1.82      misha     399:        // @todo: when name="xmlns"
1.72      paf       400:        xmlChar* attribute_value=xmlGetProp(&element, name);
1.6       parser    401:        // write out result
1.68      paf       402:        r.write_pass_lang(r.transcode(attribute_value));
1.6       parser    403: }
                    404: 
                    405: // void setAttribute(in DOMString name, in DOMString value) raises(DOMException);
1.56      paf       406: static void _setAttribute(Request& r, MethodParams& params) {
1.86      misha     407:        const xmlChar* name=as_xmlname(r, params, 0);
                    408:        const xmlChar* attribute_value=as_xmlchar(r, params, 1, XML_VALUE_MUST_BE_STRING);
                    409: 
1.67      paf       410:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       411:        xmlNode& element=get_self_element(vnode);
                    412: 
1.82      misha     413:        // @todo: when name="xmlns"
1.72      paf       414:        if(!xmlSetProp(&element, name,  attribute_value))
1.88    ! moko      415:                throw XmlException(0, r);
1.6       parser    416: }
                    417: 
                    418: // void removeAttribute(in DOMString name) raises(DOMException);
1.56      paf       419: static void _removeAttribute(Request& r, MethodParams& params) {
1.86      misha     420:        const xmlChar* name=as_xmlname(r, params, 0);
                    421: 
1.67      paf       422:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       423:        xmlNode& element=get_self_element(vnode);
1.6       parser    424: 
1.82      misha     425:        // @todo: when name="xmlns"
1.72      paf       426:        xmlUnsetProp(&element, name);
1.6       parser    427: }
                    428: 
                    429: // Attr getAttributeNode(in DOMString name);
1.56      paf       430: static void _getAttributeNode(Request& r, MethodParams& params) {
1.86      misha     431:        const xmlChar* localName=as_xmlname(r, params, 0);
                    432: 
1.67      paf       433:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       434:        VXdoc& vxdoc=vnode.get_vxdoc();
                    435:        xmlNode& element=get_self_element(vnode);
1.6       parser    436: 
1.72      paf       437:        if(xmlNode* retNode=pa_getAttributeNodeNS(element, localName, 0)){
1.6       parser    438:                // write out result
1.72      paf       439:                writeNode(r, vxdoc, retNode);
                    440:        }
1.6       parser    441: }      
                    442: 
                    443: // Attr setAttributeNode(in Attr newAttr) raises(DOMException);
1.72      paf       444: // Attr setAttributeNodeNS(in Attr newAttr) raises(DOMException);
1.56      paf       445: static void _setAttributeNode(Request& r, MethodParams& params) {
1.67      paf       446:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       447:        VXdoc& vxdoc=vnode.get_vxdoc();
                    448:        xmlNode& element=get_self_element(vnode);
                    449:        xmlDoc& xmldoc=vxdoc.get_xmldoc();
1.86      misha     450: 
1.72      paf       451:        xmlAttr& newAttr=as_attr(params, 0, "newAttr must be ATTRIBUTE node");
                    452: 
                    453:        if(newAttr.doc!=&xmldoc)
1.74      paf       454:                throw Exception("xml.dom",
1.72      paf       455:                        0,
                    456:                        "WRONG_DOCUMENT_ERR");
1.6       parser    457: 
1.72      paf       458:        if(newAttr.parent)
1.74      paf       459:                throw Exception("xml.dom",
1.72      paf       460:                        0,
                    461:                        "INUSE_ATTRIBUTE_ERR");
                    462:        
                    463:        if(xmlNode* retNode=pa_getAttributeNodeNS(element, newAttr.name, pa_xmlGetNsURI((xmlNode*)&newAttr))) {
1.19      paf       464:                // write out result
1.72      paf       465:                writeNode(r, vxdoc, retNode);
                    466:                xmlUnlinkNode(retNode);
                    467:        }
                    468: 
                    469:        pa_addAttributeNode(element, newAttr);
1.6       parser    470: }      
                    471: 
                    472: // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException);
1.56      paf       473: static void _removeAttributeNode(Request& r, MethodParams& params) {
1.86      misha     474:        xmlAttr& oldAttr=as_attr(params, 0, "oldAttr must be ATTRIBUTE node");
                    475: 
1.67      paf       476:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       477:        VXdoc& vxdoc=vnode.get_vxdoc();
                    478:        xmlNode& element=get_self_element(vnode);
                    479: 
                    480:        if(oldAttr.parent!=&element)
1.74      paf       481:                throw Exception("xml.dom",
1.72      paf       482:                        0,
                    483:                        "NOT_FOUND_ERR");
1.6       parser    484: 
1.72      paf       485:        xmlUnlinkNode((xmlNode*)&oldAttr);
                    486: 
                    487:        // write out result
                    488:        writeNode(r, vxdoc, (xmlNode*)&oldAttr);
1.6       parser    489: }      
                    490: 
                    491: // NodeList getElementsByTagName(in DOMString name);
1.86      misha     492: // '*' means all tags
1.56      paf       493: static void _getElementsByTagName(Request& r, MethodParams& params) {
1.86      misha     494:        xmlChar* tagName=as_xmlchar(r, params, 0, XML_LOCAL_NAME_MUST_BE_STRING);
                    495:        if(xmlValidateName(tagName, 0) != 0 && strcmp((const char*)tagName, "*") != 0)
                    496:                throw XmlException(0, XML_INVALID_LOCAL_NAME, tagName);
                    497: 
1.67      paf       498:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       499:        VXdoc& vxdoc=vnode.get_vxdoc();
                    500:        xmlNode& xmlnode=vnode.get_xmlnode();
1.6       parser    501: 
1.56      paf       502:        VHash& result=*new VHash;
1.72      paf       503:        AccumulateFoundInfo info={&result.hash(), &vxdoc, 0};
                    504:        pa_xmlNamedPreorderTraversal(&xmlnode, 
                    505:                                                          0, 
                    506:                                                          tagName, 
                    507:                                                          AccumulateFound,
                    508:                                                          &info);
1.6       parser    509: 
                    510:        // write out result
                    511:        r.write_no_lang(result);
                    512: }
                    513: 
1.57      paf       514: // DOM 2
                    515: 
1.58      paf       516: // DOMString getAttributeNS(in DOMString namespaceURI, in DOMString localName);
1.57      paf       517: static void _getAttributeNS(Request& r, MethodParams& params) {
1.86      misha     518:        xmlChar* namespaceURI=as_xmlnsuri(r, params, 0);
                    519:        xmlChar* localName=as_xmlname(r, params, 1);
                    520: 
1.67      paf       521:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       522:        xmlNode& element=get_self_element(vnode);
1.57      paf       523:        
1.72      paf       524:        // todo: when name="xmlns"
                    525:        xmlChar* attribute_value=xmlGetNsProp(&element, localName, namespaceURI);
1.57      paf       526:        // write out result
1.68      paf       527:        r.write_pass_lang(r.transcode(attribute_value));
1.57      paf       528: }
                    529: 
1.72      paf       530: 
1.58      paf       531: // void setAttributeNS(in DOMString namespaceURI, in DOMString qualifiedName, in DOMString value) raises(DOMException);
1.57      paf       532: static void _setAttributeNS(Request& r, MethodParams& params) {
1.86      misha     533:        const xmlChar* namespaceURI=as_xmlnsuri(r, params, 0);
                    534:        const xmlChar* qualifiedName=as_xmlqname(r, params, 1);
                    535:        const xmlChar* attribute_value=as_xmlchar(r, params, 2, XML_VALUE_MUST_BE_STRING);
                    536: 
1.67      paf       537:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       538:        xmlNode& element=get_self_element(vnode);
                    539:        VXdoc& vxdoc=vnode.get_vxdoc();
                    540:        xmlDoc& xmldoc=vxdoc.get_xmldoc();
                    541: 
                    542:        xmlChar* prefix=0;
                    543:        xmlChar* localName=xmlSplitQName2(qualifiedName, &prefix);
                    544: 
1.82      misha     545:        // @todo: name=xmlns
1.72      paf       546:        xmlAttr* attrNode;
                    547:        if(localName) {
                    548:                xmlNs& ns=pa_xmlMapNs(xmldoc, namespaceURI, prefix);
                    549:                
                    550:                attrNode=xmlSetNsProp(&element, &ns,
                    551:                        localName,
                    552:                        attribute_value);
                    553:        } else {
                    554:                attrNode=xmlSetProp(&element, 
                    555:                        qualifiedName/*unqualified, actually*/,
                    556:                        attribute_value);
                    557:        }
                    558: 
                    559:        if(!attrNode)
1.88    ! moko      560:                throw XmlException(0, r);
1.57      paf       561: }
                    562: 
1.58      paf       563: // void removeAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException);
1.57      paf       564: static void _removeAttributeNS(Request& r, MethodParams& params) {
1.86      misha     565:        const xmlChar* namespaceURI=as_xmlnsuri(r, params, 0);
                    566:        const xmlChar* localName=as_xmlname(r, params, 1);
                    567: 
1.67      paf       568:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       569:        xmlNode& element=get_self_element(vnode);
                    570:        VXdoc& vxdoc=vnode.get_vxdoc();
                    571:        xmlDoc& xmldoc=vxdoc.get_xmldoc();
                    572: 
1.82      misha     573:        // @todo: when name="xmlns"
1.72      paf       574:        xmlNs& ns=pa_xmlMapNs(xmldoc, namespaceURI, 0);
                    575:        xmlUnsetNsProp(&element, &ns, localName);
1.57      paf       576: }
                    577: 
1.58      paf       578: // Attr getAttributeNodeNS(in DOMString namespaceURI, in DOMString localName);
1.57      paf       579: static void _getAttributeNodeNS(Request& r, MethodParams& params) {
1.86      misha     580:        const xmlChar* namespaceURI=as_xmlnsuri(r, params, 0);
                    581:        const xmlChar* localName=as_xmlname(r, params, 1);
                    582: 
1.67      paf       583:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       584:        VXdoc& vxdoc=vnode.get_vxdoc();
                    585:        xmlNode& element=get_self_element(vnode);
1.57      paf       586: 
1.72      paf       587:        if(xmlNode* retNode=pa_getAttributeNodeNS(element, localName, namespaceURI)){
1.57      paf       588:                // write out result
1.72      paf       589:                writeNode(r, vxdoc, retNode);
                    590:        }
                    591: }      
1.57      paf       592: 
1.58      paf       593: // boolean hasAttribute(in DOMString name) raises(DOMException);
1.57      paf       594: static void _hasAttribute(Request& r, MethodParams& params) {
1.86      misha     595:        const xmlChar* name=as_xmlname(r, params, 0);
                    596: 
1.67      paf       597:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       598:        xmlNode& element=get_self_element(vnode);
1.57      paf       599: 
1.82      misha     600:        // @todo: when name="xmlns"
1.57      paf       601:        // write out result
1.83      misha     602:        r.write_no_lang(VBool::get(xmlHasProp(&element, name)!=0));
1.57      paf       603: }
                    604: 
1.58      paf       605: // boolean hasAttributeNS(n DOMString namespaceURI, in DOMString localName) raises(DOMException);
1.57      paf       606: static void _hasAttributeNS(Request& r, MethodParams& params) {
1.86      misha     607:        const xmlChar* namespaceURI=as_xmlnsuri(r, params, 0);
                    608:        const xmlChar* localName=as_xmlname(r, params, 1);
                    609: 
1.67      paf       610:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       611:        xmlNode& element=get_self_element(vnode);
1.57      paf       612: 
                    613:        // write out result
1.83      misha     614:        r.write_no_lang(VBool::get(xmlHasNsProp(&element, localName, namespaceURI)!=0));
1.57      paf       615: }
                    616: 
1.78      misha     617: // boolean hasAttributes
                    618: static void _hasAttributes(Request& r, MethodParams&) {
                    619:        VXnode& vnode=GET_SELF(r, VXnode);
                    620:        xmlNode& element=get_self_element(vnode);
                    621: 
                    622:        // write out result
1.83      misha     623:        r.write_no_lang(VBool::get(element.properties!=0));
1.78      misha     624: }
                    625: 
1.86      misha     626: // NodeList getElementsByTagNameNS(in DOMString namespaceURI, in DOMString localName);
                    627: // '*' as namespaceURI means get all namespaces
                    628: // '*' as localName means get all tags
1.56      paf       629: static void _getElementsByTagNameNS(Request& r, MethodParams& params) {
1.86      misha     630:        xmlChar* namespaceURI=as_xmlchar(r, params, 0, XML_NAMESPACEURI_MUST_BE_STRING);
                    631: 
                    632:        xmlChar* localName=as_xmlchar(r, params, 1, XML_LOCAL_NAME_MUST_BE_STRING);
                    633:        if(xmlValidateName(localName, 0) != 0 && strcmp((const char*)localName, "*") != 0)
                    634:                throw XmlException(0, XML_INVALID_LOCAL_NAME, localName);
                    635: 
1.67      paf       636:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       637:        VXdoc& vdoc=vnode.get_vxdoc();
                    638:        xmlDoc& xmldoc=vdoc.get_xmldoc();
1.39      paf       639: 
1.56      paf       640:        VHash& result=*new VHash;
1.72      paf       641:        AccumulateFoundInfo info={&result.hash(), &vdoc, 0};
                    642:        pa_xmlNamedPreorderTraversal((xmlNode*)&xmldoc, 
                    643:                                                          namespaceURI, 
                    644:                                                          localName, 
                    645:                                                          AccumulateFound,
                    646:                                                          &info);
1.39      paf       647: 
                    648:        // write out result
                    649:        r.write_no_lang(result);
                    650: }
                    651: 
1.72      paf       652: 
1.6       parser    653: // void normalize();
1.72      paf       654: static void _normalize(Request&, MethodParams&) {
                    655: /*maybe someday
1.56      paf       656:        VXnode& vnode=GET_SELF(r, VXnode);
1.72      paf       657:        xmlNode& selfNode=vnode.get_xmlnode();
1.6       parser    658: 
1.19      paf       659:        gdome_n_normalize(selfNode, &exc);
                    660:        if(exc)
1.60      paf       661:                throw XmlException(0, exc);
1.72      paf       662: */
1.6       parser    663: }
1.25      paf       664: 
1.66      paf       665: #ifndef DOXYGEN
                    666: struct Register_one_ns_info {
                    667:        Request* r;
                    668:        xmlXPathContextPtr ctxt;
                    669: };
                    670: #endif
                    671: static void register_one_ns(
                    672:                                                                  HashStringValue::key_type key, 
                    673:                                                                  HashStringValue::value_type value, 
                    674:                                                                  Register_one_ns_info* info) {
                    675:        if(const String* svalue=value->get_string())
                    676:                xmlXPathRegisterNs(info->ctxt, 
1.72      paf       677:                        info->r->transcode(key), 
                    678:                        info->r->transcode(*svalue));
1.66      paf       679:        else
1.77      misha     680:                throw Exception(PARSER_RUNTIME,
1.66      paf       681:                        new String(key, String::L_TAINTED),
                    682:                        "value is %s, must be string or number", value->type());
                    683: }
1.56      paf       684: static void _selectX(Request& r, MethodParams& params,
                    685:                                         void (*handler)(Request& r,
1.26      paf       686:                                                          const String& expression, 
                    687:                                                          xmlXPathObject_auto_ptr res,
1.67      paf       688:                                                          VXdoc& xdoc,
1.72      paf       689:                                                          Value*& result)) 
                    690: {
1.56      paf       691:        VXnode& vnode=GET_SELF(r, VXnode);
1.74      paf       692:        xmlNode& xmlnode=vnode.get_xmlnode();
1.72      paf       693:        VXdoc& vdoc=vnode.get_vxdoc();
                    694:        xmlDoc& xmldoc=vdoc.get_xmldoc();
1.1       parser    695: 
                    696:        // expression
1.56      paf       697:        const String& expression=params.as_string(0, "expression must be string");
1.72      paf       698:        xmlXPathContext_auto_ptr ctxt(xmlXPathNewContext(&xmldoc));
1.67      paf       699:        {
1.66      paf       700:                Register_one_ns_info info={&r, ctxt.get()};
1.75      paf       701:                vdoc.search_namespaces.hash().for_each<Register_one_ns_info*>(register_one_ns, &info);
1.66      paf       702:        }
1.74      paf       703:        ctxt->node=&xmlnode;
1.25      paf       704:        /*error to stderr for now*/
                    705:        xmlXPathObject_auto_ptr res(
1.72      paf       706:                xmlXPathEvalExpression(r.transcode(expression), ctxt.get()));
1.28      paf       707: 
1.72      paf       708:        if(xmlHaveGenericErrors())
1.88    ! moko      709:                throw XmlException(0, r);
1.25      paf       710: 
1.56      paf       711:        Value* result=0;
1.25      paf       712:        if(res.get())
1.72      paf       713:                handler(r, expression, res, vdoc, result);
1.44      paf       714:        if(result)
1.26      paf       715:                r.write_no_lang(*result);
                    716: }
1.25      paf       717: 
1.72      paf       718: static void selectNodesHandler(Request&,
1.56      paf       719:                               const String& expression,
                    720:                               xmlXPathObject_auto_ptr res,
1.67      paf       721:                                   VXdoc& xdoc,
1.56      paf       722:                               Value*& result) {
                    723:        VHash& vhash=*new VHash;  result=&vhash;
1.26      paf       724:        switch(res->type) {
                    725:        case XPATH_UNDEFINED: 
                    726:                break;
                    727:        case XPATH_NODESET:
1.40      paf       728:                if(res->nodesetval)
                    729:                        if(int size=res->nodesetval->nodeNr) {
1.56      paf       730:                                HashStringValue& hash=vhash.hash();
                    731:                                for(int i=0; i<size; i++)
                    732:                                        hash.put(
1.59      paf       733:                                                String::Body::Format(i), 
1.72      paf       734:                                                &xdoc.wrap(*res->nodesetval->nodeTab[i]));
1.1       parser    735:                        }
1.26      paf       736:                break;
                    737:        default: 
1.77      misha     738:                throw Exception(PARSER_RUNTIME,
1.26      paf       739:                        &expression,
                    740:                        "wrong xmlXPathEvalExpression result type (%d)", res->type);
                    741:                break; // never
                    742:        }
                    743: }
                    744: 
1.56      paf       745: static void selectNodeHandler(Request& r,
                    746:                              const String& expression,
1.67      paf       747:                                  xmlXPathObject_auto_ptr res,
                    748:                                  VXdoc& xdoc,
                    749:                                  Value*& result) {
1.26      paf       750:        switch(res->type) {
                    751:        case XPATH_UNDEFINED: 
                    752:                break;
                    753:        case XPATH_NODESET: 
1.80      misha     754:                if(res->nodesetval && res->nodesetval->nodeNr) { // empty result strangely has NODESET  res->type
1.26      paf       755:                        if(res->nodesetval->nodeNr>1)
1.77      misha     756:                                throw Exception(PARSER_RUNTIME,
1.56      paf       757:                                        &expression,
                    758:                                        "resulted not in a single node (%d)", res->nodesetval->nodeNr);
1.26      paf       759:                        
1.72      paf       760:                        result=&xdoc.wrap(*res->nodesetval->nodeTab[0]);
1.25      paf       761:                }
1.26      paf       762:                break;
                    763:        case XPATH_BOOLEAN: 
1.83      misha     764:                result=&VBool::get(res->boolval!=0);
1.26      paf       765:                break;
                    766:        case XPATH_NUMBER: 
1.56      paf       767:                result=new VDouble(res->floatval);
1.26      paf       768:                break;
                    769:        case XPATH_STRING:
1.56      paf       770:                result=new VString(r.transcode((xmlChar*)res->stringval));
1.26      paf       771:                break;
                    772:        default: 
1.77      misha     773:                throw Exception(PARSER_RUNTIME,
1.26      paf       774:                        &expression,
                    775:                        "wrong xmlXPathEvalExpression result type (%d)", res->type);
                    776:        }
                    777: }
                    778: 
1.62      paf       779: static void selectBoolHandler(Request&,
1.56      paf       780:                              const String& expression,
                    781:                              xmlXPathObject_auto_ptr res,
1.67      paf       782:                                  VXdoc& /*xdoc*/,
1.56      paf       783:                              Value*& result) {
1.26      paf       784:        switch(res->type) {
                    785:        case XPATH_BOOLEAN: 
1.83      misha     786:                result=&VBool::get(res->boolval!=0);
1.26      paf       787:                break;
                    788:        case XPATH_NODESET: 
1.40      paf       789:                if(!(res->nodesetval && res->nodesetval->nodeNr))
1.26      paf       790:                        break;
                    791:                // else[nodeset] fall down to default
                    792:        default: 
1.77      misha     793:                throw Exception(PARSER_RUNTIME,
1.26      paf       794:                        &expression,
                    795:                        "wrong xmlXPathEvalExpression result type (%d)", res->type);
                    796:                break; // never
                    797:        }
                    798: }
1.1       parser    799: 
1.62      paf       800: static void selectNumberHandler(Request&,
1.56      paf       801:                                const String& expression,
                    802:                                xmlXPathObject_auto_ptr res,
1.67      paf       803:                                VXdoc& /*xdoc*/,
1.56      paf       804:                                Value*& result) {
1.26      paf       805:        switch(res->type) {
                    806:        case XPATH_NUMBER: 
1.56      paf       807:                result=new VDouble(res->floatval);
1.26      paf       808:                break;
                    809:        case XPATH_NODESET:
1.40      paf       810:                if(!(res->nodesetval && res->nodesetval->nodeNr))
1.26      paf       811:                        break;
                    812:                // else[nodeset] fall down to default
                    813:        default: 
1.77      misha     814:                throw Exception(PARSER_RUNTIME,
1.26      paf       815:                        &expression,
                    816:                        "wrong xmlXPathEvalExpression result type (%d)", res->type);
                    817:                break; // never
                    818:        }
                    819: }
                    820: 
1.56      paf       821: static void selectStringHandler(Request& r,
1.26      paf       822:                                                          const String& expression,
                    823:                                                          xmlXPathObject_auto_ptr res,
1.67      paf       824:                                                          VXdoc& /*xdoc*/,
1.56      paf       825:                                                          Value*& result) {
1.26      paf       826:        switch(res->type) {
                    827:        case XPATH_UNDEFINED: 
                    828:                break;
                    829:        case XPATH_STRING:
1.56      paf       830:                result=new VString(r.transcode((xmlChar*)res->stringval));
1.26      paf       831:                break;
                    832:        case XPATH_NODESET: 
1.40      paf       833:                if(!(res->nodesetval && res->nodesetval->nodeNr))
1.26      paf       834:                        break;
                    835:                // else[nodeset] fall down to default
                    836:        default: 
1.77      misha     837:                throw Exception(PARSER_RUNTIME,
1.26      paf       838:                        &expression,
                    839:                        "wrong xmlXPathEvalExpression result type (%d)", res->type);
                    840:                break; // never
1.1       parser    841:        }
                    842: }
1.25      paf       843: 
1.56      paf       844: static void _select(Request& r, MethodParams& params) {
                    845:        _selectX(r, params,
1.26      paf       846:                selectNodesHandler);
                    847: }
                    848: 
1.56      paf       849: static void _selectSingle(Request& r, MethodParams& params) {
                    850:        _selectX(r, params,
1.26      paf       851:                selectNodeHandler);
                    852: }
1.1       parser    853: 
1.56      paf       854: static void _selectBool(Request& r, MethodParams& params) {
                    855:        _selectX(r, params,
1.26      paf       856:                selectBoolHandler);
                    857: }
1.20      paf       858: 
1.56      paf       859: static void _selectNumber(Request& r, MethodParams& params) {
                    860:        _selectX(r, params,
1.26      paf       861:                selectNumberHandler);
                    862: }
1.24      paf       863: 
1.56      paf       864: static void _selectString(Request& r, MethodParams& params) {
                    865:        _selectX(r, params,
1.26      paf       866:                selectStringHandler);
1.1       parser    867: }
1.20      paf       868: 
1.1       parser    869: // constructor
                    870: 
1.56      paf       871: /// @bug one can change const and ruin other's work, we need unchangable VIntConst class
                    872: MXnode::MXnode(const char* aname, VStateless_class *abase):
                    873:        Methoded(aname?aname:"xnode", abase)
1.44      paf       874: {
1.6       parser    875:        /// DOM1 node
                    876: 
                    877:        // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException);
                    878:        add_native_method("insertBefore", Method::CT_DYNAMIC, _insertBefore, 2, 2);
                    879:        // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException);
                    880:        add_native_method("replaceChild", Method::CT_DYNAMIC, _replaceChild, 2, 2);
                    881:        // Node removeChild(in Node oldChild) raises(DOMException);
                    882:        add_native_method("removeChild", Method::CT_DYNAMIC, _removeChild, 1, 1);
                    883:        // Node appendChild(in Node newChild) raises(DOMException);
                    884:        add_native_method("appendChild", Method::CT_DYNAMIC, _appendChild, 1, 1);
                    885:        // boolean hasChildNodes();
                    886:        add_native_method("hasChildNodes", Method::CT_DYNAMIC, _hasChildNodes, 0, 0);
                    887:        // Node cloneNode(in boolean deep);
                    888:        add_native_method("cloneNode", Method::CT_DYNAMIC, _cloneNode, 1, 1);
                    889: 
                    890:        /// DOM1 element
                    891: 
                    892:        // DOMString getAttribute(in DOMString name);
                    893:        add_native_method("getAttribute", Method::CT_DYNAMIC, _getAttribute, 1, 1);
                    894:        // void setAttribute(in DOMString name, in DOMString value) raises(DOMException);
                    895:        add_native_method("setAttribute", Method::CT_DYNAMIC, _setAttribute, 2, 2);
                    896:        // void removeAttribute(in DOMString name) raises(DOMException);
                    897:        add_native_method("removeAttribute", Method::CT_DYNAMIC, _removeAttribute, 1, 1);
                    898:        // Attr getAttributeNode(in DOMString name);
                    899:        add_native_method("getAttributeNode", Method::CT_DYNAMIC, _getAttributeNode, 1, 1);
                    900:        // Attr setAttributeNode(in Attr newAttr) raises(DOMException);
                    901:        add_native_method("setAttributeNode", Method::CT_DYNAMIC, _setAttributeNode, 1, 1);
                    902:        // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException);
                    903:        add_native_method("removeAttributeNode", Method::CT_DYNAMIC, _removeAttributeNode, 1, 1);
                    904:        // NodeList getElementsByTagName(in DOMString name);
                    905:        add_native_method("getElementsByTagName", Method::CT_DYNAMIC, _getElementsByTagName, 1, 1);
1.39      paf       906:        // NodeList getElementsByTagNameNS(in DOMString namespaceURI, in DOMString localName);
                    907:        add_native_method("getElementsByTagNameNS", Method::CT_DYNAMIC, _getElementsByTagNameNS, 2, 2);
1.6       parser    908:        // void normalize();
                    909:        add_native_method("normalize", Method::CT_DYNAMIC, _normalize, 0, 0);
1.57      paf       910: 
                    911:        /// DOM2 element
                    912: 
1.58      paf       913:        // DOMString getAttributeNS(in DOMString namespaceURI, in DOMString localName);
1.57      paf       914:        add_native_method("getAttributeNS", Method::CT_DYNAMIC, _getAttributeNS, 2, 2);
1.58      paf       915:        // void setAttributeNS(in DOMString namespaceURI, in DOMString qualifiedName, in DOMString value) raises(DOMException);
1.57      paf       916:        add_native_method("setAttributeNS", Method::CT_DYNAMIC, _setAttributeNS, 3, 3);
1.58      paf       917:        // void removeAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException);
1.57      paf       918:        add_native_method("removeAttributeNS", Method::CT_DYNAMIC, _removeAttributeNS, 2, 2);
1.58      paf       919:        // Attr getAttributeNodeNS(in DOMString namespaceURI, in DOMString localName);
1.57      paf       920:        add_native_method("getAttributeNodeNS", Method::CT_DYNAMIC, _getAttributeNodeNS, 2, 2);
                    921:        // Attr setAttributeNodeNS(in Attr newAttr) raises(DOMException);
1.72      paf       922:        add_native_method("setAttributeNodeNS", Method::CT_DYNAMIC, _setAttributeNode, 1, 1);
1.58      paf       923:        // boolean hasAttribute(in DOMString name) raises(DOMException);
1.57      paf       924:        add_native_method("hasAttribute", Method::CT_DYNAMIC, _hasAttribute, 1, 1);
1.58      paf       925:        // boolean hasAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException);
1.57      paf       926:        add_native_method("hasAttributeNS", Method::CT_DYNAMIC, _hasAttributeNS, 2, 2);
1.78      misha     927:        // boolean hasAttributes
                    928:        add_native_method("hasAttributes", Method::CT_DYNAMIC, _hasAttributes, 0, 0);
                    929:        
1.6       parser    930: 
                    931:        /// parser
1.1       parser    932:        // ^node.select[/some/xpath/query] = hash $.#[dnode]
1.67      paf       933:        add_native_method("select", Method::CT_DYNAMIC, _select, 1, 1);
1.1       parser    934: 
1.26      paf       935:        // ^node.selectSingle[/some/xpath/query] = first node [if any]
1.67      paf       936:        add_native_method("selectSingle", Method::CT_DYNAMIC, _selectSingle, 1, 1);
1.26      paf       937:        // ^node.selectBool[/some/xpath/query] = bool value [if any]
1.67      paf       938:        add_native_method("selectBool", Method::CT_DYNAMIC, _selectBool, 1, 1);
1.26      paf       939:        // ^node.selectNumber[/some/xpath/query] = double value [if any]
1.67      paf       940:        add_native_method("selectNumber", Method::CT_DYNAMIC, _selectNumber, 1, 1);
1.26      paf       941:        // ^node.selectString[/some/xpath/query] = strinv value [if any]
1.67      paf       942:        add_native_method("selectString", Method::CT_DYNAMIC, _selectString, 1, 1);
1.20      paf       943: 
1.2       parser    944:        // consts
                    945: 
1.19      paf       946: #define CONST(name) \
1.72      paf       947:        consts.put(String::Body(#name), new VInt(XML_##name))
                    948: #define CONST2(name, value) \
                    949:        consts.put(String::Body(#name), new VInt(value))
1.2       parser    950: 
1.19      paf       951:        CONST(ELEMENT_NODE);
1.56      paf       952:        CONST(ATTRIBUTE_NODE);
                    953:        CONST(TEXT_NODE);
                    954:        CONST(CDATA_SECTION_NODE);
1.72      paf       955:        CONST2(ENTITY_REFERENCE_NODE, XML_ENTITY_REF_NODE);
1.56      paf       956:        CONST(ENTITY_NODE);
1.72      paf       957:        CONST2(PROCESSING_INSTRUCTION_NODE, XML_PI_NODE);
1.56      paf       958:        CONST(COMMENT_NODE);
                    959:        CONST(DOCUMENT_NODE);
                    960:        CONST(DOCUMENT_TYPE_NODE);
1.72      paf       961:        CONST2(DOCUMENT_FRAGMENT_NODE, XML_DOCUMENT_FRAG_NODE);
1.56      paf       962:        CONST(NOTATION_NODE);
                    963: }
1.1       parser    964: 
1.56      paf       965: #else
1.3       parser    966: 
1.1       parser    967: // global variable
                    968: 
1.56      paf       969: DECLARE_CLASS_VAR(xnode, 0, 0); // fictive
1.1       parser    970: 
                    971: #endif

E-mail: