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

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

E-mail: