|
|
| version 1.7, 2001/10/16 14:43:30 | version 1.71, 2005/08/09 08:14:48 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: @b dom parser class. | Parser: @b dom parser class. |
| Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| $Id$ | |
| */ | */ |
| #include "classes.h" | #include "classes.h" |
| #ifdef XML | #ifdef XML |
| static const char * const IDENT_XNODE_C="$Date$"; | |
| #include "pa_vmethod_frame.h" | |
| #include "pa_charset.h" | |
| #include "pa_request.h" | #include "pa_request.h" |
| #include "pa_vxnode.h" | #include "pa_vxnode.h" |
| #include "pa_vxdoc.h" | |
| #include "pa_vvoid.h" | |
| #include "pa_xml_exception.h" | |
| #include "xnode.h" | #include "xnode.h" |
| #include "libxml/xpath.h" | |
| #include "libxml/xpathInternals.h" | |
| #include <util/XMLString.hpp> | // global variable |
| #include <XalanSourceTree/XalanSourceTreeDOMSupport.hpp> | |
| #include <XPath/XPathEvaluator.hpp> | DECLARE_CLASS_VAR(xnode, new MXnode, 0); |
| #include <XPath/NodeRefList.hpp> | |
| #include <XalanDOM/XalanElement.hpp> | |
| #include <XalanDOM/XalanAttr.hpp> | |
| #include <XalanDOM/XalanNodeList.hpp> | |
| // defines | // classes |
| #define XNODE_CLASS_NAME "xnode" | class xmlXPathObject_auto_ptr { |
| public: | |
| explicit xmlXPathObject_auto_ptr(xmlXPathObject *_APtr = 0) | |
| : _Owns(_APtr != 0), _Ptr(_APtr) {} | |
| xmlXPathObject_auto_ptr(const xmlXPathObject_auto_ptr& _Y) | |
| : _Owns(_Y._Owns), _Ptr(_Y.release()) {} | |
| xmlXPathObject_auto_ptr& operator=(const xmlXPathObject_auto_ptr& _Y) | |
| {if (this != &_Y) | |
| {if (_Ptr != _Y.get()) | |
| {if (_Owns && _Ptr) | |
| xmlXPathFreeObject(_Ptr); | |
| _Owns = _Y._Owns; } | |
| else if (_Y._Owns) | |
| _Owns = true; | |
| _Ptr = _Y.release(); } | |
| return (*this); } | |
| ~xmlXPathObject_auto_ptr() | |
| {if (_Owns && _Ptr) | |
| xmlXPathFreeObject(_Ptr); } | |
| xmlXPathObject& operator*() const | |
| {return (*get()); } | |
| xmlXPathObject *operator->() const | |
| {return (get()); } | |
| xmlXPathObject *get() const | |
| {return (_Ptr); } | |
| xmlXPathObject *release() const | |
| {((xmlXPathObject_auto_ptr *)this)->_Owns = false; | |
| return (_Ptr); } | |
| private: | |
| bool _Owns; | |
| xmlXPathObject *_Ptr; | |
| }; | |
| class xmlXPathContext_auto_ptr { | |
| public: | |
| explicit xmlXPathContext_auto_ptr(xmlXPathContext *_APtr = 0) | |
| : _Owns(_APtr != 0), _Ptr(_APtr) {} | |
| xmlXPathContext_auto_ptr(const xmlXPathContext_auto_ptr& _Y) | |
| : _Owns(_Y._Owns), _Ptr(_Y.release()) {} | |
| xmlXPathContext_auto_ptr& operator=(const xmlXPathContext_auto_ptr& _Y) | |
| {if (this != &_Y) | |
| {if (_Ptr != _Y.get()) | |
| {if (_Owns && _Ptr) | |
| xmlXPathFreeContext(_Ptr); | |
| _Owns = _Y._Owns; } | |
| else if (_Y._Owns) | |
| _Owns = true; | |
| _Ptr = _Y.release(); } | |
| return (*this); } | |
| ~xmlXPathContext_auto_ptr() | |
| {if (_Owns && _Ptr) | |
| xmlXPathFreeContext(_Ptr); } | |
| xmlXPathContext& operator*() const | |
| {return (*get()); } | |
| xmlXPathContext *operator->() const | |
| {return (get()); } | |
| xmlXPathContext *get() const | |
| {return (_Ptr); } | |
| xmlXPathContext *release() const | |
| {((xmlXPathContext_auto_ptr *)this)->_Owns = false; | |
| return (_Ptr); } | |
| private: | |
| bool _Owns; | |
| xmlXPathContext *_Ptr; | |
| }; | |
| // helpers | // helpers |
| XalanNode& as_node(Pool& pool, const String& method_name, MethodParams *params, | GdomeNode* as_node(MethodParams& params, |
| int index, const char *msg) { | int index, const char* msg) { |
| Value& value=params->as_no_junction(index, msg); | GdomeNode* result; |
| if(strcmp(value.type(), VXNODE_TYPE)!=0) | Value& value=params.as_no_junction(index, msg); |
| PTHROW(0, 0, | if(Value* vxnode=value.as(VXNODE_TYPE, false)) |
| &method_name, | result=static_cast<VXnode*>(vxnode)->get_node(); |
| else { | |
| throw Exception("parser.runtime", | |
| 0, | |
| msg); | msg); |
| } | |
| VXnode& vnode=*static_cast<VXnode *>(&value); | return result; |
| return vnode.get_node(pool, &method_name); | |
| } | } |
| // helpers | // helpers |
| XalanAttr& as_attr(Pool& pool, const String& method_name, MethodParams *params, | GdomeAttr* as_attr(MethodParams& params, |
| int index, const char *msg) { | int index, const char* msg) { |
| XalanNode& node=as_node(pool, method_name, params, index, msg); | GdomeNode* node=as_node(params, index, msg); |
| GdomeException exc; | |
| if(node.getNodeType()!=XalanNode::ATTRIBUTE_NODE) | if(gdome_n_nodeType(node, &exc)!=GDOME_ATTRIBUTE_NODE) |
| PTHROW(0, 0, | throw Exception("parser.runtime", |
| &method_name, | 0, |
| msg); | msg); |
| return *reinterpret_cast<XalanAttr *>(&node); | return GDOME_A(node); |
| } | } |
| // methods | // methods |
| Line 59 XalanAttr& as_attr(Pool& pool, const Str | Line 130 XalanAttr& as_attr(Pool& pool, const Str |
| // DOM1 node | // DOM1 node |
| // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException); | // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException); |
| static void _insertBefore(Request& r, const String& method_name, MethodParams *params) { | static void _insertBefore(Request& r, MethodParams& params) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| VXnode& vnode=*static_cast<VXnode *>(r.self); | GdomeNode* selfNode=vnode.get_node(); |
| XalanNode& node=vnode.get_node(pool, &method_name); | GdomeNode* newChild=as_node(params, 0, "newChild must be node"); |
| GdomeNode* refChild=as_node(params, 1, "refChild must be node"); | |
| XalanNode& newChild=as_node(pool, method_name, params, 0, "newChild must be node"); | |
| XalanNode& refChild=as_node(pool, method_name, params, 1, "refChild must be node"); | |
| try { | GdomeException exc; |
| node.insertBefore(&newChild, &refChild); | if(GdomeNode* retNode=gdome_n_insertBefore(selfNode, newChild, refChild, &exc)) { |
| } catch(const XalanDOMException& e) { | // write out result |
| pool.exception()._throw(pool, &method_name, e); | r.write_no_lang(*new VXnode(&r.charsets, vnode.get_xdoc(), retNode)); |
| } | } else |
| throw XmlException(0, exc); | |
| } | } |
| // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException); | // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException); |
| static void _replaceChild(Request& r, const String& method_name, MethodParams *params) { | static void _replaceChild(Request& r, MethodParams& params) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| VXnode& vnode=*static_cast<VXnode *>(r.self); | GdomeNode* selfNode=vnode.get_node(); |
| XalanNode& node=vnode.get_node(pool, &method_name); | GdomeNode* newChild=as_node(params, 0, "newChild must be node"); |
| GdomeNode* oldChild=as_node(params, 1, "oldChild must be node"); | |
| XalanNode& newChild=as_node(pool, method_name, params, 0, "newChild must be node"); | |
| XalanNode& refChild=as_node(pool, method_name, params, 1, "refChild must be node"); | |
| try { | GdomeException exc; |
| node.replaceChild(&newChild, &refChild); | if(GdomeNode* retNode=gdome_n_replaceChild(selfNode, newChild, oldChild, &exc)) { |
| } catch(const XalanDOMException& e) { | // write out result |
| pool.exception()._throw(pool, &method_name, e); | r.write_no_lang(*new VXnode(&r.charsets, vnode.get_xdoc(), retNode)); |
| } | } else |
| throw XmlException(0, exc); | |
| } | } |
| // Node removeChild(in Node oldChild) raises(DOMException); | // Node removeChild(in Node oldChild) raises(DOMException); |
| static void _removeChild(Request& r, const String& method_name, MethodParams *params) { | static void _removeChild(Request& r, MethodParams& params) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| VXnode& vnode=*static_cast<VXnode *>(r.self); | GdomeNode* selfNode=vnode.get_node(); |
| XalanNode& node=vnode.get_node(pool, &method_name); | GdomeNode* oldChild=as_node(params, 0, "oldChild must be node"); |
| XalanNode& oldChild=as_node(pool, method_name, params, 0, "oldChild must be node"); | |
| try { | GdomeException exc; |
| node.removeChild(&oldChild); | if(GdomeNode* retNode=gdome_n_removeChild(selfNode, oldChild, &exc)) { |
| } catch(const XalanDOMException& e) { | // write out result |
| pool.exception()._throw(pool, &method_name, e); | r.write_no_lang(*new VXnode(&r.charsets, vnode.get_xdoc(), retNode)); |
| } | } else |
| throw XmlException(0, exc); | |
| } | } |
| // Node appendChild(in Node newChild) raises(DOMException); | // Node appendChild(in Node newChild) raises(DOMException); |
| static void _appendChild(Request& r, const String& method_name, MethodParams *params) { | static void _appendChild(Request& r, MethodParams& params) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| VXnode& vnode=*static_cast<VXnode *>(r.self); | GdomeNode* selfNode=vnode.get_node(); |
| XalanNode& node=vnode.get_node(pool, &method_name); | GdomeNode* newChild=as_node(params, 0, "newChild must be node"); |
| XalanNode& newChild=as_node(pool, method_name, params, 0, "newChild must be node"); | |
| try { | GdomeException exc; |
| node.appendChild(&newChild); | if(GdomeNode* retNode=gdome_n_appendChild(selfNode, newChild, &exc)) { |
| } catch(const XalanDOMException& e) { | // write out result |
| pool.exception()._throw(pool, &method_name, e); | r.write_no_lang(*new VXnode(&r.charsets, vnode.get_xdoc(), retNode)); |
| } | } else |
| throw XmlException(0, exc); | |
| } | } |
| // boolean hasChildNodes(); | // boolean hasChildNodes(); |
| static void _hasChildNodes(Request& r, const String& method_name, MethodParams *) { | static void _hasChildNodes(Request& r, MethodParams&) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| VXnode& vnode=*static_cast<VXnode *>(r.self); | GdomeNode* node=vnode.get_node(); |
| XalanNode& node=vnode.get_node(pool, &method_name); | |
| GdomeException exc; | |
| // write out result | // write out result |
| VBool& result=*new(pool) VBool(pool, node.hasChildNodes()); | bool result=gdome_n_hasChildNodes(node, &exc)!=0; |
| result.set_name(method_name); | r.write_no_lang(*new VBool(result)); |
| r.write_no_lang(result); | |
| } | } |
| // Node cloneNode(in boolean deep); | // Node cloneNode(in boolean deep); |
| /// @test 1. who frees it up? 2. ownerDocument=? | static void _cloneNode(Request& r, MethodParams& params) { |
| static void _cloneNode(Request& r, const String& method_name, MethodParams *params) { | VXnode& vnode=GET_SELF(r, VXnode); |
| Pool& pool=r.pool(); | GdomeNode* node=vnode.get_node(); |
| VXnode& vnode=*static_cast<VXnode *>(r.self); | |
| XalanNode& node=vnode.get_node(pool, &method_name); | |
| bool deep=params->as_bool(0, "deep must be bool", r); | bool deep=params.as_bool(0, "deep must be bool", r); |
| GdomeException exc; | |
| // write out result | // write out result |
| VXnode& result=*new(pool) VXnode(pool, node.cloneNode(deep)); | r.write_no_lang(*new VXnode(&r.charsets, vnode.get_xdoc(), gdome_n_cloneNode(node, deep, &exc))); |
| result.set_name(method_name); | |
| r.write_no_lang(result); | |
| } | } |
| // DOM1 element | // DOM1 element |
| XalanElement& get_self_element(Request& r, const String& method_name) { | GdomeElement* get_self_element(VXnode& vnode) { |
| Pool& pool=r.pool(); | GdomeNode* node=vnode.get_node(); |
| VXnode& vnode=*static_cast<VXnode *>(r.self); | |
| XalanNode& node=vnode.get_node(pool, &method_name); | GdomeException exc; |
| if(gdome_n_nodeType(node, &exc)!=GDOME_ELEMENT_NODE) | |
| if(node.getNodeType()!=XalanNode::ELEMENT_NODE) | throw Exception("parser.runtime", |
| PTHROW(0, 0, | 0, |
| &method_name, | "method can only be called on nodes of ELEMENT type"); |
| "method can be called on node of ELEMENT type"); | |
| return *reinterpret_cast<XalanElement *>(&node); | |
| } | |
| // DOMString getAttribute(in DOMString name); | |
| static void _getAttribute(Request& r, const String& method_name, MethodParams *params) { | |
| Pool& pool=r.pool(); | |
| XalanElement& element=get_self_element(r, method_name); | |
| const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS); | |
| const XalanDOMString& attribute_value=element.getAttribute(XalanDOMString(name)); | return GDOME_EL(node); |
| } | |
| /// @bug attribute_value must be freed! [// DOMString getAttribute(in DOMString name); | |
| static void _getAttribute(Request& r, MethodParams& params) { | |
| VXnode& vnode=GET_SELF(r, VXnode); | |
| GdomeElement* element=get_self_element(vnode); | |
| const String& name=params.as_string(0, "name must be string"); | |
| GdomeException exc; | |
| GdomeDOMString *attribute_value= | |
| gdome_el_getAttribute(element, r.transcode(name).use(), &exc); | |
| // write out result | // write out result |
| r.write_no_lang(*new(pool) VString(pool.transcode(attribute_value))); | r.write_pass_lang(r.transcode(attribute_value)); |
| } | } |
| // void setAttribute(in DOMString name, in DOMString value) raises(DOMException); | // void setAttribute(in DOMString name, in DOMString value) raises(DOMException); |
| static void _setAttribute(Request& r, const String& method_name, MethodParams *params) { | static void _setAttribute(Request& r, MethodParams& params) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| XalanElement& element=get_self_element(r, method_name); | GdomeElement* element=get_self_element(vnode); |
| const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS); | const String& name=params.as_string(0, "name must be string"); |
| const char *attribute_value=params->as_string(1, "value must not be code").cstr(String::UL_AS_IS); | const String& attribute_value=params.as_string(1, "value must be string"); |
| try { | GdomeException exc; |
| element.setAttribute( | gdome_el_setAttribute(element, |
| XalanDOMString(name), | r.transcode(name).use(), |
| XalanDOMString(attribute_value)); | r.transcode(attribute_value).use(), |
| } catch(const XalanDOMException& e) { | &exc); |
| pool.exception()._throw(pool, &method_name, e); | if(exc) |
| } | throw XmlException(0, exc); |
| } | } |
| // void removeAttribute(in DOMString name) raises(DOMException); | // void removeAttribute(in DOMString name) raises(DOMException); |
| static void _removeAttribute(Request& r, const String& method_name, MethodParams *params) { | static void _removeAttribute(Request& r, MethodParams& params) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| XalanElement& element=get_self_element(r, method_name); | GdomeElement* element=get_self_element(vnode); |
| const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS); | const String& name=params.as_string(0, "name must be string"); |
| try { | GdomeException exc; |
| element.removeAttribute(XalanDOMString(name)); | gdome_el_removeAttribute(element, r.transcode(name).use(), &exc); |
| } catch(const XalanDOMException& e) { | if(exc) |
| pool.exception()._throw(pool, &method_name, e); | throw XmlException(0, exc); |
| } | |
| } | } |
| // Attr getAttributeNode(in DOMString name); | // Attr getAttributeNode(in DOMString name); |
| static void _getAttributeNode(Request& r, const String& method_name, MethodParams *params) { | static void _getAttributeNode(Request& r, MethodParams& params) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| XalanElement& element=get_self_element(r, method_name); | GdomeElement* element=get_self_element(vnode); |
| const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS); | const String& name=params.as_string(0, "name must be string"); |
| if(XalanAttr *attr=element.getAttributeNode(XalanDOMString(name))) { | GdomeException exc; |
| if(GdomeAttr *attr=gdome_el_getAttributeNode(element, | |
| r.transcode(name).use(), &exc)) { | |
| // write out result | // write out result |
| VXnode& result=*new(pool) VXnode(pool, attr); | r.write_no_lang(*new VXnode(&r.charsets, vnode.get_xdoc(), (GdomeNode* )attr)); |
| r.write_no_lang(result); | } else if(exc) |
| } | throw XmlException(0, exc); |
| } | } |
| // Attr setAttributeNode(in Attr newAttr) raises(DOMException); | // Attr setAttributeNode(in Attr newAttr) raises(DOMException); |
| static void _setAttributeNode(Request& r, const String& method_name, MethodParams *params) { | static void _setAttributeNode(Request& r, MethodParams& params) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| XalanElement& element=get_self_element(r, method_name); | GdomeElement* element=get_self_element(vnode); |
| XalanAttr& newAttr=as_attr(pool, method_name, params, 0, "newAttr must be ATTRIBUTE node"); | GdomeAttr * newAttr=as_attr(params, 0, "newAttr must be ATTRIBUTE node"); |
| try { | GdomeException exc; |
| if(XalanAttr *returnAttr=element.setAttributeNode(&newAttr)) { | if(GdomeAttr *returnAttr=gdome_el_setAttributeNode(element, newAttr, &exc)) { |
| // write out result | // write out result |
| VXnode& result=*new(pool) VXnode(pool, returnAttr); | r.write_no_lang(*new VXnode(&r.charsets, vnode.get_xdoc(), (GdomeNode* )returnAttr)); |
| r.write_no_lang(result); | } else |
| } | throw XmlException(0, exc); |
| } catch(const XalanDOMException& e) { | |
| pool.exception()._throw(pool, &method_name, e); | |
| } | |
| } | } |
| // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException); | // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException); |
| static void _removeAttributeNode(Request& r, const String& method_name, MethodParams *params) { | static void _removeAttributeNode(Request& r, MethodParams& params) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| XalanElement& element=get_self_element(r, method_name); | GdomeElement* element=get_self_element(vnode); |
| XalanAttr& oldAttr=as_attr(pool, method_name, params, 0, "oldAttr must be ATTRIBUTE node"); | GdomeAttr * oldAttr=as_attr(params, 0, "oldAttr must be ATTRIBUTE node"); |
| try { | GdomeException exc; |
| /*XalanAttr *returnAttr*/element.removeAttributeNode(&oldAttr)); | gdome_el_removeAttributeNode(element, oldAttr, &exc); |
| } catch(const XalanDOMException& e) { | if(exc) |
| pool.exception()._throw(pool, &method_name, e); | throw XmlException(0, exc); |
| } | |
| } | } |
| // NodeList getElementsByTagName(in DOMString name); | // NodeList getElementsByTagName(in DOMString name); |
| static void _getElementsByTagName(Request& r, const String& method_name, MethodParams *params) { | static void _getElementsByTagName(Request& r, MethodParams& params) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| XalanElement& element=get_self_element(r, method_name); | GdomeElement* element=get_self_element(vnode); |
| const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS); | const String& name=params.as_string(0, "name must be string"); |
| VHash& result=*new(pool) VHash(pool); | VHash& result=*new VHash; |
| if(const XalanNodeList *nodes= | GdomeException exc; |
| element.getElementsByTagName(XalanDOMString(name))) { | if(GdomeNodeList *nodes= |
| for(int i=0; i<nodes->getLength(); i++) { | gdome_el_getElementsByTagName(element, r.transcode(name).use(), &exc)) { |
| String& skey=*new(pool) String(pool); | gulong length=gdome_nl_length(nodes, &exc); |
| { | for(gulong i=0; i<length; i++) |
| char *buf=(char *)pool.malloc(MAX_NUMBER); | result.hash().put( |
| snprintf(buf, MAX_NUMBER, "%d", i); | String::Body::Format(i), |
| skey << buf; | new VXnode(&r.charsets, vnode.get_xdoc(), gdome_nl_item(nodes, i, &exc))); |
| } | } else if(exc) |
| throw XmlException(0, exc); | |
| result.hash().put(skey, new(pool) VXnode(pool, nodes->item(i))); | |
| } | |
| } | |
| // write out result | // write out result |
| r.write_no_lang(result); | r.write_no_lang(result); |
| } | } |
| // void normalize(); | // DOM 2 |
| static void _normalize(Request& r, const String& method_name, MethodParams *) { | |
| XalanElement& element=get_self_element(r, method_name); | // DOMString getAttributeNS(in DOMString namespaceURI, in DOMString localName); |
| static void _getAttributeNS(Request& r, MethodParams& params) { | |
| VXnode& vnode=GET_SELF(r, VXnode); | |
| GdomeElement* element=get_self_element(vnode); | |
| const String& namespaceURI=params.as_string(0, "namespaceURI must be string"); | |
| const String& localName=params.as_string(0, "localName must be string"); | |
| element.normalize(); | GdomeException exc; |
| GdomeDOMString *attribute_value= | |
| gdome_el_getAttributeNS(element, | |
| r.transcode(namespaceURI).use(), | |
| r.transcode(localName).use(), &exc); | |
| // write out result | |
| r.write_pass_lang(r.transcode(attribute_value)); | |
| } | } |
| // void setAttributeNS(in DOMString namespaceURI, in DOMString qualifiedName, in DOMString value) raises(DOMException); | |
| static void _setAttributeNS(Request& r, MethodParams& params) { | |
| VXnode& vnode=GET_SELF(r, VXnode); | |
| GdomeElement* element=get_self_element(vnode); | |
| const String& namespaceURI=params.as_string(0, "namespaceURI must be string"); | |
| const String& qualifiedName=params.as_string(1, "qualifiedName must be string"); | |
| const String& attribute_value=params.as_string(2, "value must be string"); | |
| GdomeException exc; | |
| gdome_el_setAttributeNS(element, | |
| r.transcode(namespaceURI).use(), | |
| r.transcode(qualifiedName).use(), | |
| r.transcode(attribute_value).use(), | |
| &exc); | |
| if(exc) | |
| throw XmlException(0, exc); | |
| } | |
| // void removeAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException); | |
| static void _removeAttributeNS(Request& r, MethodParams& params) { | |
| VXnode& vnode=GET_SELF(r, VXnode); | |
| GdomeElement* element=get_self_element(vnode); | |
| const String& namespaceURI=params.as_string(0, "namespaceURI must be string"); | |
| const String& localName=params.as_string(1, "localName must be string"); | |
| GdomeException exc; | |
| gdome_el_removeAttributeNS(element, | |
| r.transcode(namespaceURI).use(), | |
| r.transcode(localName).use(), | |
| &exc); | |
| if(exc) | |
| throw XmlException(0, exc); | |
| } | |
| // Attr getAttributeNodeNS(in DOMString namespaceURI, in DOMString localName); | |
| static void _getAttributeNodeNS(Request& r, MethodParams& params) { | |
| VXnode& vnode=GET_SELF(r, VXnode); | |
| GdomeElement* element=get_self_element(vnode); | |
| const String& namespaceURI=params.as_string(0, "namespaceURI must be string"); | |
| const String& name=params.as_string(1, "name must be string"); | |
| GdomeException exc; | |
| if(GdomeAttr *attr=gdome_el_getAttributeNodeNS(element, | |
| r.transcode(namespaceURI).use(), r.transcode(name).use(), &exc)) { | |
| // write out result | |
| r.write_no_lang(*new VXnode(&r.charsets, vnode.get_xdoc(), (GdomeNode* )attr)); | |
| } else if(exc) | |
| throw XmlException(0, exc); | |
| } | |
| static void _select(Request& r, const String& method_name, MethodParams *params) { | // Attr setAttributeNodeNS(in Attr newAttr) raises(DOMException); |
| // _asm int 3; | static void _setAttributeNodeNS(Request& r, MethodParams& params) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| VXnode& vnode=*static_cast<VXnode *>(r.self); | GdomeElement* element=get_self_element(vnode); |
| GdomeAttr * newAttr=as_attr(params, 0, "newAttr must be ATTRIBUTE node"); | |
| // expression | GdomeException exc; |
| const String& expression=params->as_string(0, "expression must not be code"); | if(GdomeAttr *returnAttr=gdome_el_setAttributeNodeNS(element, newAttr, &exc)) { |
| const char *expression_cstr=expression.cstr(String::UL_AS_IS); | // write out result |
| XalanDOMString dstring(expression_cstr); | r.write_no_lang(*new VXnode(&r.charsets, vnode.get_xdoc(), (GdomeNode* )returnAttr)); |
| const XalanDOMChar *expression_dcstr=dstring.c_str(); | } else |
| throw XmlException(0, exc); | |
| XPathEvaluator evaluator; | } |
| // We'll use these to parse the XML file. | |
| XalanSourceTreeDOMSupport dom_support; | |
| try { | |
| NodeRefList list=evaluator.selectNodeList(dom_support, | |
| &vnode.get_node(pool, &method_name), | |
| expression_dcstr); | |
| VHash& result=*new(pool) VHash(pool); | |
| for(int i=0; i<list.getLength(); i++) { | |
| String& skey=*new(pool) String(pool); | |
| { | |
| char *buf=(char *)pool.malloc(MAX_NUMBER); | |
| snprintf(buf, MAX_NUMBER, "%d", i); | |
| skey << buf; | |
| } | |
| result.hash().put(skey, new(pool) VXnode(pool, list.item(i))); | // boolean hasAttribute(in DOMString name) raises(DOMException); |
| } | static void _hasAttribute(Request& r, MethodParams& params) { |
| result.set_name(method_name); | VXnode& vnode=GET_SELF(r, VXnode); |
| r.write_no_lang(result); | GdomeElement* element=get_self_element(vnode); |
| } catch(const XSLException& e) { | |
| pool.exception()._throw(pool, &expression, e); | const String& name=params.as_string(0, "name must be string"); |
| GdomeException exc; | |
| // write out result | |
| bool result=gdome_el_hasAttribute(element, | |
| r.transcode(name).use(), | |
| &exc)!=0; | |
| r.write_no_lang(*new VBool(result)); | |
| } | |
| // boolean hasAttributeNS(n DOMString namespaceURI, in DOMString localName) raises(DOMException); | |
| static void _hasAttributeNS(Request& r, MethodParams& params) { | |
| VXnode& vnode=GET_SELF(r, VXnode); | |
| GdomeElement* element=get_self_element(vnode); | |
| const String& namespaceURI=params.as_string(0, "namespaceURI must be string"); | |
| const String& localName=params.as_string(1, "localName must be string"); | |
| GdomeException exc; | |
| // write out result | |
| bool result=gdome_el_hasAttributeNS(element, | |
| r.transcode(namespaceURI).use(), | |
| r.transcode(localName).use(), | |
| &exc)!=0; | |
| r.write_no_lang(*new VBool(result)); | |
| } | |
| static void _getElementsByTagNameNS(Request& r, MethodParams& params) { | |
| VXnode& vnode=GET_SELF(r, VXnode); | |
| GdomeElement* element=get_self_element(vnode); | |
| // namespaceURI;localName | |
| const String& namespaceURI=params.as_string(0, "namespaceURI must be string"); | |
| const String& localName=params.as_string(1, "localName must be string"); | |
| GdomeException exc; | |
| VHash& result=*new VHash; | |
| if(GdomeNodeList *nodes= | |
| gdome_el_getElementsByTagNameNS( | |
| element, | |
| r.transcode(namespaceURI).use(), | |
| r.transcode(localName).use(), | |
| &exc)) { | |
| gulong length=gdome_nl_length(nodes, &exc); | |
| for(gulong i=0; i<length; i++) | |
| result.hash().put( | |
| String::Body::Format(i), | |
| new VXnode(&r.charsets, vnode.get_xdoc(), gdome_nl_item(nodes, i, &exc))); | |
| } | } |
| // write out result | |
| r.write_no_lang(result); | |
| } | } |
| static void _select_single(Request& r, const String& method_name, MethodParams *params) { | // void normalize(); |
| // _asm int 3; | static void _normalize(Request& r, MethodParams&) { |
| Pool& pool=r.pool(); | VXnode& vnode=GET_SELF(r, VXnode); |
| VXnode& vnode=*static_cast<VXnode *>(r.self); | GdomeNode* selfNode=vnode.get_node(); |
| GdomeException exc; | |
| gdome_n_normalize(selfNode, &exc); | |
| if(exc) | |
| throw XmlException(0, exc); | |
| } | |
| #ifndef DOXYGEN | |
| struct Register_one_ns_info { | |
| Request* r; | |
| xmlXPathContextPtr ctxt; | |
| }; | |
| #endif | |
| static void register_one_ns( | |
| HashStringValue::key_type key, | |
| HashStringValue::value_type value, | |
| Register_one_ns_info* info) { | |
| if(const String* svalue=value->get_string()) | |
| xmlXPathRegisterNs(info->ctxt, | |
| BAD_CAST info->r->transcode(key)->str, | |
| BAD_CAST info->r->transcode(*svalue)->str); | |
| else | |
| throw Exception("parser.runtime", | |
| new String(key, String::L_TAINTED), | |
| "value is %s, must be string or number", value->type()); | |
| } | |
| static void _selectX(Request& r, MethodParams& params, | |
| void (*handler)(Request& r, | |
| const String& expression, | |
| xmlXPathObject_auto_ptr res, | |
| VXdoc& xdoc, | |
| Value*& result)) { | |
| VXnode& vnode=GET_SELF(r, VXnode); | |
| // expression | // expression |
| const String& expression=params->as_string(0, "expression must not be code"); | const String& expression=params.as_string(0, "expression must be string"); |
| const char *expression_cstr=expression.cstr(String::UL_AS_IS); | GdomeException exc; |
| XalanDOMString dstring(expression_cstr); | GdomeNode* dome_node=vnode.get_node(); |
| const XalanDOMChar *expression_dcstr=dstring.c_str(); | GdomeDocument *dome_document=gdome_n_ownerDocument(dome_node, &exc); |
| if(!dome_document) // document does not own itself, so ownerDocument = 0 | |
| XPathEvaluator evaluator; | dome_document=GDOME_DOC(dome_node); // and we need downcast |
| // Initialize the XalanSourceTree subsystem... | xmlDoc *xml_document=gdome_xml_doc_get_xmlDoc(dome_document); |
| // XalanSourceTreeInit theSourceTreeInit; | xmlXPathContext_auto_ptr ctxt(xmlXPathNewContext(xml_document)); |
| // We'll use these to parse the XML file. | { |
| XalanSourceTreeDOMSupport dom_support; | Register_one_ns_info info={&r, ctxt.get()}; |
| vnode.get_xdoc().search_namespaces.hash().for_each(register_one_ns, &info); | |
| try { | } |
| if(XalanNode *node=evaluator.selectSingleNode(dom_support, | ctxt->node=gdome_xml_n_get_xmlNode(dome_node); |
| &vnode.get_node(pool, &method_name), | /*error to stderr for now*/ |
| expression_dcstr)) { | xmlXPathObject_auto_ptr res( |
| xmlXPathEvalExpression(BAD_CAST r.transcode(expression)->str, ctxt.get())); | |
| VXnode& result=*new(pool) VXnode(pool, node); | |
| result.set_name(method_name); | if(xmlHaveGenericErrors()) { |
| r.write_no_lang(result); | GdomeException exc=0; |
| } | throw XmlException(&expression, exc); |
| } catch(const XSLException& e) { | } |
| pool.exception()._throw(pool, &expression, e); | |
| Value* result=0; | |
| if(res.get()) | |
| handler(r, expression, res, vnode.get_xdoc(), result); | |
| if(result) | |
| r.write_no_lang(*result); | |
| } | |
| static void selectNodesHandler(Request& r, | |
| const String& expression, | |
| xmlXPathObject_auto_ptr res, | |
| VXdoc& xdoc, | |
| Value*& result) { | |
| VHash& vhash=*new VHash; result=&vhash; | |
| switch(res->type) { | |
| case XPATH_UNDEFINED: | |
| break; | |
| case XPATH_NODESET: | |
| if(res->nodesetval) | |
| if(int size=res->nodesetval->nodeNr) { | |
| HashStringValue& hash=vhash.hash(); | |
| for(int i=0; i<size; i++) | |
| hash.put( | |
| String::Body::Format(i), | |
| new VXnode( | |
| &r.charsets, | |
| xdoc, | |
| gdome_xml_n_mkref(res->nodesetval->nodeTab[i]))); | |
| } | |
| break; | |
| default: | |
| throw Exception(0, | |
| &expression, | |
| "wrong xmlXPathEvalExpression result type (%d)", res->type); | |
| break; // never | |
| } | } |
| } | } |
| // constructor | static void selectNodeHandler(Request& r, |
| const String& expression, | |
| xmlXPathObject_auto_ptr res, | |
| VXdoc& xdoc, | |
| Value*& result) { | |
| switch(res->type) { | |
| case XPATH_UNDEFINED: | |
| break; | |
| case XPATH_NODESET: | |
| if(res->nodesetval && res->nodesetval->nodeNr) { // empty result strangly has NODESET res->type | |
| if(res->nodesetval->nodeNr>1) | |
| throw Exception("parser.runtime", | |
| &expression, | |
| "resulted not in a single node (%d)", res->nodesetval->nodeNr); | |
| result=new VXnode( | |
| &r.charsets, | |
| xdoc, | |
| gdome_xml_n_mkref(res->nodesetval->nodeTab[0])); | |
| } | |
| break; | |
| case XPATH_BOOLEAN: | |
| result=new VBool(res->boolval!=0); | |
| break; | |
| case XPATH_NUMBER: | |
| result=new VDouble(res->floatval); | |
| break; | |
| case XPATH_STRING: | |
| result=new VString(r.transcode((xmlChar*)res->stringval)); | |
| break; | |
| default: | |
| throw Exception("parser.runtime", | |
| &expression, | |
| "wrong xmlXPathEvalExpression result type (%d)", res->type); | |
| // result=0; | |
| break; // never | |
| } | |
| } | |
| static void selectBoolHandler(Request&, | |
| const String& expression, | |
| xmlXPathObject_auto_ptr res, | |
| VXdoc& /*xdoc*/, | |
| Value*& result) { | |
| switch(res->type) { | |
| case XPATH_BOOLEAN: | |
| result=new VBool(res->boolval!=0); | |
| break; | |
| case XPATH_NODESET: | |
| if(!(res->nodesetval && res->nodesetval->nodeNr)) | |
| break; | |
| // else[nodeset] fall down to default | |
| default: | |
| throw Exception("parser.runtime", | |
| &expression, | |
| "wrong xmlXPathEvalExpression result type (%d)", res->type); | |
| break; // never | |
| } | |
| } | |
| static void selectNumberHandler(Request&, | |
| const String& expression, | |
| xmlXPathObject_auto_ptr res, | |
| VXdoc& /*xdoc*/, | |
| Value*& result) { | |
| switch(res->type) { | |
| case XPATH_NUMBER: | |
| result=new VDouble(res->floatval); | |
| break; | |
| case XPATH_NODESET: | |
| if(!(res->nodesetval && res->nodesetval->nodeNr)) | |
| break; | |
| // else[nodeset] fall down to default | |
| default: | |
| throw Exception("parser.runtime", | |
| &expression, | |
| "wrong xmlXPathEvalExpression result type (%d)", res->type); | |
| break; // never | |
| } | |
| } | |
| static void selectStringHandler(Request& r, | |
| const String& expression, | |
| xmlXPathObject_auto_ptr res, | |
| VXdoc& /*xdoc*/, | |
| Value*& result) { | |
| switch(res->type) { | |
| case XPATH_UNDEFINED: | |
| break; | |
| case XPATH_STRING: | |
| result=new VString(r.transcode((xmlChar*)res->stringval)); | |
| break; | |
| case XPATH_NODESET: | |
| if(!(res->nodesetval && res->nodesetval->nodeNr)) | |
| break; | |
| // else[nodeset] fall down to default | |
| default: | |
| throw Exception("parser.runtime", | |
| &expression, | |
| "wrong xmlXPathEvalExpression result type (%d)", res->type); | |
| break; // never | |
| } | |
| } | |
| static void _select(Request& r, MethodParams& params) { | |
| _selectX(r, params, | |
| selectNodesHandler); | |
| } | |
| static void _selectSingle(Request& r, MethodParams& params) { | |
| _selectX(r, params, | |
| selectNodeHandler); | |
| } | |
| static void _selectBool(Request& r, MethodParams& params) { | |
| _selectX(r, params, | |
| selectBoolHandler); | |
| } | |
| static void _selectNumber(Request& r, MethodParams& params) { | |
| _selectX(r, params, | |
| selectNumberHandler); | |
| } | |
| static void _selectString(Request& r, MethodParams& params) { | |
| _selectX(r, params, | |
| selectStringHandler); | |
| } | |
| MXnode::MXnode(Pool& apool) : Methoded(apool), | // constructor |
| consts(apool) { | |
| set_name(*NEW String(pool(), XNODE_CLASS_NAME)); | |
| /// @bug one can change const and ruin other's work, we need unchangable VIntConst class | |
| MXnode::MXnode(const char* aname, VStateless_class *abase): | |
| Methoded(aname?aname:"xnode", abase) | |
| { | |
| /// DOM1 node | /// DOM1 node |
| // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException); | // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException); |
| Line 385 MXnode::MXnode(Pool& apool) : Methoded(a | Line 737 MXnode::MXnode(Pool& apool) : Methoded(a |
| add_native_method("removeAttributeNode", Method::CT_DYNAMIC, _removeAttributeNode, 1, 1); | add_native_method("removeAttributeNode", Method::CT_DYNAMIC, _removeAttributeNode, 1, 1); |
| // NodeList getElementsByTagName(in DOMString name); | // NodeList getElementsByTagName(in DOMString name); |
| add_native_method("getElementsByTagName", Method::CT_DYNAMIC, _getElementsByTagName, 1, 1); | add_native_method("getElementsByTagName", Method::CT_DYNAMIC, _getElementsByTagName, 1, 1); |
| // NodeList getElementsByTagNameNS(in DOMString namespaceURI, in DOMString localName); | |
| add_native_method("getElementsByTagNameNS", Method::CT_DYNAMIC, _getElementsByTagNameNS, 2, 2); | |
| // void normalize(); | // void normalize(); |
| add_native_method("normalize", Method::CT_DYNAMIC, _normalize, 0, 0); | add_native_method("normalize", Method::CT_DYNAMIC, _normalize, 0, 0); |
| /// parser | /// DOM2 element |
| // DOMString getAttributeNS(in DOMString namespaceURI, in DOMString localName); | |
| add_native_method("getAttributeNS", Method::CT_DYNAMIC, _getAttributeNS, 2, 2); | |
| // void setAttributeNS(in DOMString namespaceURI, in DOMString qualifiedName, in DOMString value) raises(DOMException); | |
| add_native_method("setAttributeNS", Method::CT_DYNAMIC, _setAttributeNS, 3, 3); | |
| // void removeAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException); | |
| add_native_method("removeAttributeNS", Method::CT_DYNAMIC, _removeAttributeNS, 2, 2); | |
| // Attr getAttributeNodeNS(in DOMString namespaceURI, in DOMString localName); | |
| add_native_method("getAttributeNodeNS", Method::CT_DYNAMIC, _getAttributeNodeNS, 2, 2); | |
| // Attr setAttributeNodeNS(in Attr newAttr) raises(DOMException); | |
| add_native_method("setAttributeNodeNS", Method::CT_DYNAMIC, _setAttributeNodeNS, 1, 1); | |
| // boolean hasAttribute(in DOMString name) raises(DOMException); | |
| add_native_method("hasAttribute", Method::CT_DYNAMIC, _hasAttribute, 1, 1); | |
| // boolean hasAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException); | |
| add_native_method("hasAttributeNS", Method::CT_DYNAMIC, _hasAttributeNS, 2, 2); | |
| /// parser | |
| // ^node.select[/some/xpath/query] = hash $.#[dnode] | // ^node.select[/some/xpath/query] = hash $.#[dnode] |
| add_native_method("select", Method::CT_DYNAMIC, _select, 1, 1); | add_native_method("select", Method::CT_DYNAMIC, _select, 1, 1); |
| // ^node.selectSingle[/some/xpath/query] = first dnode | // ^node.selectSingle[/some/xpath/query] = first node [if any] |
| add_native_method("selectSingle", Method::CT_DYNAMIC, _select_single, 1, 1); | add_native_method("selectSingle", Method::CT_DYNAMIC, _selectSingle, 1, 1); |
| // ^node.selectBool[/some/xpath/query] = bool value [if any] | |
| add_native_method("selectBool", Method::CT_DYNAMIC, _selectBool, 1, 1); | |
| // ^node.selectNumber[/some/xpath/query] = double value [if any] | |
| add_native_method("selectNumber", Method::CT_DYNAMIC, _selectNumber, 1, 1); | |
| // ^node.selectString[/some/xpath/query] = strinv value [if any] | |
| add_native_method("selectString", Method::CT_DYNAMIC, _selectString, 1, 1); | |
| // consts | // consts |
| #define CONST(name, value) \ | #define CONST(name) \ |
| consts.put(*new(pool()) String(pool(), #name), new(pool()) VInt(pool(), value)) | consts.put(String::Body(#name), new VInt(GDOME_##name)) |
| CONST(ELEMENT_NODE, 1); | |
| CONST(ATTRIBUTE_NODE, 2); | |
| CONST(TEXT_NODE, 3); | |
| CONST(CDATA_SECTION_NODE, 4); | |
| CONST(ENTITY_REFERENCE_NODE, 5); | |
| CONST(ENTITY_NODE, 6); | |
| CONST(PROCESSING_INSTRUCTION_NODE, 7); | |
| CONST(COMMENT_NODE, 8); | |
| CONST(DOCUMENT_NODE, 9); | |
| CONST(DOCUMENT_TYPE_NODE, 10); | |
| CONST(DOCUMENT_FRAGMENT_NODE, 11); | |
| CONST(NOTATION_NODE, 12); | |
| CONST(ELEMENT_NODE); | |
| CONST(ATTRIBUTE_NODE); | |
| CONST(TEXT_NODE); | |
| CONST(CDATA_SECTION_NODE); | |
| CONST(ENTITY_REFERENCE_NODE); | |
| CONST(ENTITY_NODE); | |
| CONST(PROCESSING_INSTRUCTION_NODE); | |
| CONST(COMMENT_NODE); | |
| CONST(DOCUMENT_NODE); | |
| CONST(DOCUMENT_TYPE_NODE); | |
| CONST(DOCUMENT_FRAGMENT_NODE); | |
| CONST(NOTATION_NODE); | |
| } | } |
| // global variable | #else |
| Methoded *Xnode_class; | // global variable |
| #endif | DECLARE_CLASS_VAR(xnode, 0, 0); // fictive |
| // creator | |
| Methoded *MXnode_create(Pool& pool) { | |
| return | |
| #ifdef XML | |
| Xnode_class=new(pool) MXnode(pool) | |
| #else | |
| 0 | |
| #endif | #endif |
| ; | |
| } |