--- parser3/src/classes/xnode.C 2007/08/20 08:56:46 1.78 +++ parser3/src/classes/xnode.C 2016/11/01 23:10:41 1.95 @@ -1,14 +1,12 @@ /** @file Parser: @b dom parser class. - Copyright (c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com) + Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) */ #include "classes.h" #ifdef XML -static const char * const IDENT_XNODE_C="$Date: 2007/08/20 08:56:46 $"; - #include "pa_vmethod_frame.h" #include "pa_charset.h" @@ -23,9 +21,7 @@ static const char * const IDENT_XNODE_C= #include "libxml/xpath.h" #include "libxml/xpathInternals.h" -// global variable - -DECLARE_CLASS_VAR(xnode, new MXnode, 0); +volatile const char * IDENT_XNODE_C="$Id: xnode.C,v 1.95 2016/11/01 23:10:41 moko Exp $" IDENT_XNODE_H; // classes @@ -99,7 +95,7 @@ private: xmlNode& as_node(MethodParams& params, int index, const char* msg) { Value& value=params.as_no_junction(index, msg); - if(Value* vxnode=value.as(VXNODE_TYPE, false)) + if(Value* vxnode=value.as(VXNODE_TYPE)) return static_cast(vxnode)->get_xmlnode(); else throw Exception(PARSER_RUNTIME, @@ -111,6 +107,31 @@ xmlChar* as_xmlchar(Request& r, MethodPa return r.transcode(params.as_string(index, msg)); } +xmlChar* as_xmlqname(Request& r, MethodParams& params, int index, const char* msg) { + xmlChar* qname=r.transcode(params.as_string(index, msg ? msg : XML_QUALIFIED_NAME_MUST_BE_STRING)); + if(xmlValidateQName(qname, 0)) + throw XmlException(0, XML_INVALID_QUALIFIED_NAME, qname); + return qname; +} + +xmlChar* as_xmlncname(Request& r, MethodParams& params, int index, const char* msg) { + xmlChar* ncname=r.transcode(params.as_string(index, msg ? msg : XML_NC_NAME_MUST_BE_STRING)); + if(xmlValidateNCName(ncname, 0)) + throw XmlException(0, XML_INVALID_NC_NAME, ncname); + return ncname; +} + +xmlChar* as_xmlname(Request& r, MethodParams& params, int index, const char* msg) { + xmlChar* localName=r.transcode(params.as_string(index, msg ? msg : XML_LOCAL_NAME_MUST_BE_STRING)); + if(xmlValidateName(localName, 0)) + throw XmlException(0, XML_INVALID_LOCAL_NAME, localName); + return localName; +} + +xmlChar* as_xmlnsuri(Request& r, MethodParams& params, int index) { + return r.transcode(params.as_string(index, XML_NAMESPACEURI_MUST_BE_STRING)); +} + xmlAttr& as_attr(MethodParams& params, int index, const char* msg) { xmlNode& xmlnode=as_node(params, index, msg); if(xmlnode.type!=XML_ATTRIBUTE_NODE) @@ -123,10 +144,10 @@ xmlAttr& as_attr(MethodParams& params, i static void writeNode(Request& r, VXdoc& xdoc, xmlNode* node) { if(!node|| xmlHaveGenericErrors()) - throw XmlException(0); // OOM, bad name, things like that + throw XmlException(0, r); // OOM, bad name, things like that // write out result - r.write_no_lang(xdoc.wrap(*node)); + r.write(xdoc.wrap(*node)); } static xmlNode* pa_getAttributeNodeNS(xmlNode& selfNode, @@ -137,7 +158,7 @@ static xmlNode* pa_getAttributeNodeNS(xm currentNode; currentNode=currentNode->next) { - if(!namespaceURI || currentNode->ns && xmlStrEqual(currentNode->ns->href, namespaceURI)) + if(!namespaceURI || (currentNode->ns && xmlStrEqual(currentNode->ns->href, namespaceURI)) ) if(!localName || xmlStrEqual(currentNode->name, localName)) return currentNode; } @@ -159,7 +180,7 @@ xmlNs& pa_xmlMapNs(xmlDoc& doc, const xm if (cur == NULL) { cur = xmlNewNs (NULL, href, prefix); if(!cur || xmlHaveGenericErrors()) - throw XmlException(0); + throw XmlException(); cur->next = doc.oldNs; doc.oldNs = cur; } @@ -167,7 +188,7 @@ xmlNs& pa_xmlMapNs(xmlDoc& doc, const xm return *cur; } -/// todo: проверить, обновляется ли parent! +/// @todo: проверить, обновляется ли parent! static void pa_addAttributeNode(xmlNode& selfNode, xmlAttr& attrNode) { if(attrNode.type!=XML_ATTRIBUTE_NODE) @@ -247,12 +268,13 @@ pa_xmlNamedPreorderTraversal ( // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException); static void _insertBefore(Request& r, MethodParams& params) { + xmlNode& newChild=as_node(params, 0, "newChild must be node"); + xmlNode& refChild=as_node(params, 1, "refChild must be node"); + VXnode& vnode=GET_SELF(r, VXnode); VXdoc& vxdoc=vnode.get_vxdoc(); //xmlNode& selfNode=vnode.get_xmlnode(); - xmlNode& newChild=as_node(params, 0, "newChild must be node"); - xmlNode& refChild=as_node(params, 1, "refChild must be node"); xmlNode* retNode=xmlAddPrevSibling(&refChild, &newChild); // write out result @@ -261,12 +283,13 @@ static void _insertBefore(Request& r, Me // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException); static void _replaceChild(Request& r, MethodParams& params) { + xmlNode& newChild=as_node(params, 0, "newChild must be node"); + xmlNode& oldChild=as_node(params, 1, "oldChild must be node"); + VXnode& vnode=GET_SELF(r, VXnode); VXdoc& vxdoc=vnode.get_vxdoc(); xmlDoc& xmldoc=vxdoc.get_xmldoc(); xmlNode& selfNode=vnode.get_xmlnode(); - xmlNode& newChild=as_node(params, 0, "newChild must be node"); - xmlNode& oldChild=as_node(params, 1, "oldChild must be node"); if(newChild.doc!=&xmldoc) throw Exception("xml.dom", @@ -296,11 +319,12 @@ static void _replaceChild(Request& r, Me // Node removeChild(in Node oldChild) raises(DOMException); static void _removeChild(Request& r, MethodParams& params) { + xmlNode& oldChild=as_node(params, 0, "refChild must be node"); + VXnode& vnode=GET_SELF(r, VXnode); VXdoc& vxdoc=vnode.get_vxdoc(); xmlDoc& xmldoc=vxdoc.get_xmldoc(); // xmlNode& selfNode=vnode.get_xmlnode(); - xmlNode& oldChild=as_node(params, 0, "refChild must be node"); if(oldChild.doc!=&xmldoc) throw Exception("xml.dom", @@ -314,10 +338,11 @@ static void _removeChild(Request& r, Met // Node appendChild(in Node newChild) raises(DOMException); static void _appendChild(Request& r, MethodParams& params) { + xmlNode& newChild=as_node(params, 0, "newChild must be node"); + VXnode& vnode=GET_SELF(r, VXnode); VXdoc& vxdoc=vnode.get_vxdoc(); xmlNode& selfNode=vnode.get_xmlnode(); - xmlNode& newChild=as_node(params, 0, "newChild must be node"); xmlNode* retNode=xmlAddChild(&selfNode, &newChild); // write out result @@ -330,19 +355,18 @@ static void _hasChildNodes(Request& r, M xmlNode& node=vnode.get_xmlnode(); // write out result - bool result=node.children!=0; - r.write_no_lang(*new VBool(result)); + r.write(VBool::get(node.children!=0)); } // Node cloneNode(in boolean deep); static void _cloneNode(Request& r, MethodParams& params) { + bool deep=params.as_bool(0, "deep must be bool", r); + VXnode& vnode=GET_SELF(r, VXnode); xmlNode& selfNode=vnode.get_xmlnode(); VXdoc& vxdoc=vnode.get_vxdoc(); xmlDoc& xmldoc=vxdoc.get_xmldoc(); - bool deep=params.as_bool(0, "deep must be bool", r); - xmlNode* retNode=xmlDocCopyNode(&selfNode, &xmldoc, deep?1: 0); // write out result writeNode(r, vxdoc, retNode); @@ -361,46 +385,50 @@ xmlNode& get_self_element(VXnode& vnode) return node; } - +// DOMString getAttribute(in DOMString name); static void _getAttribute(Request& r, MethodParams& params) { + const xmlChar* name=as_xmlname(r, params, 0); + VXnode& vnode=GET_SELF(r, VXnode); xmlNode& element=get_self_element(vnode); - const xmlChar* name=as_xmlchar(r, params, 0, "name must be string"); - // todo: when name="xmlns" + // @todo: when name="xmlns" xmlChar* attribute_value=xmlGetProp(&element, name); // write out result - r.write_pass_lang(r.transcode(attribute_value)); + r.write(r.transcode(attribute_value)); } // void setAttribute(in DOMString name, in DOMString value) raises(DOMException); static void _setAttribute(Request& r, MethodParams& params) { + const xmlChar* name=as_xmlname(r, params, 0); + const xmlChar* attribute_value=as_xmlchar(r, params, 1, XML_VALUE_MUST_BE_STRING); + VXnode& vnode=GET_SELF(r, VXnode); xmlNode& element=get_self_element(vnode); - const xmlChar* name=as_xmlchar(r, params, 0, "name must be string"); - const xmlChar* attribute_value=as_xmlchar(r, params, 1, "value must be string"); - // todo: when name="xmlns" + // @todo: when name="xmlns" if(!xmlSetProp(&element, name, attribute_value)) - throw XmlException(0); + throw XmlException(0, r); } // void removeAttribute(in DOMString name) raises(DOMException); static void _removeAttribute(Request& r, MethodParams& params) { + const xmlChar* name=as_xmlname(r, params, 0); + VXnode& vnode=GET_SELF(r, VXnode); xmlNode& element=get_self_element(vnode); - const xmlChar* name=as_xmlchar(r, params, 0, "name must be string"); - // todo: when name="xmlns" + // @todo: when name="xmlns" xmlUnsetProp(&element, name); } // Attr getAttributeNode(in DOMString name); static void _getAttributeNode(Request& r, MethodParams& params) { + const xmlChar* localName=as_xmlname(r, params, 0); + VXnode& vnode=GET_SELF(r, VXnode); VXdoc& vxdoc=vnode.get_vxdoc(); xmlNode& element=get_self_element(vnode); - const xmlChar* localName=as_xmlchar(r, params, 0, "name must be string"); if(xmlNode* retNode=pa_getAttributeNodeNS(element, localName, 0)){ // write out result @@ -415,6 +443,7 @@ static void _setAttributeNode(Request& r VXdoc& vxdoc=vnode.get_vxdoc(); xmlNode& element=get_self_element(vnode); xmlDoc& xmldoc=vxdoc.get_xmldoc(); + xmlAttr& newAttr=as_attr(params, 0, "newAttr must be ATTRIBUTE node"); if(newAttr.doc!=&xmldoc) @@ -438,10 +467,11 @@ static void _setAttributeNode(Request& r // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException); static void _removeAttributeNode(Request& r, MethodParams& params) { + xmlAttr& oldAttr=as_attr(params, 0, "oldAttr must be ATTRIBUTE node"); + VXnode& vnode=GET_SELF(r, VXnode); VXdoc& vxdoc=vnode.get_vxdoc(); xmlNode& element=get_self_element(vnode); - xmlAttr& oldAttr=as_attr(params, 0, "oldAttr must be ATTRIBUTE node"); if(oldAttr.parent!=&element) throw Exception("xml.dom", @@ -455,13 +485,16 @@ static void _removeAttributeNode(Request } // NodeList getElementsByTagName(in DOMString name); +// '*' means all tags static void _getElementsByTagName(Request& r, MethodParams& params) { + xmlChar* tagName=as_xmlchar(r, params, 0, XML_LOCAL_NAME_MUST_BE_STRING); + if(xmlValidateName(tagName, 0) != 0 && strcmp((const char*)tagName, "*") != 0) + throw XmlException(0, XML_INVALID_LOCAL_NAME, tagName); + VXnode& vnode=GET_SELF(r, VXnode); VXdoc& vxdoc=vnode.get_vxdoc(); xmlNode& xmlnode=vnode.get_xmlnode(); - xmlChar* tagName=as_xmlchar(r, params, 0, "name must be string"); - VHash& result=*new VHash; AccumulateFoundInfo info={&result.hash(), &vxdoc, 0}; pa_xmlNamedPreorderTraversal(&xmlnode, @@ -471,40 +504,41 @@ static void _getElementsByTagName(Reques &info); // write out result - r.write_no_lang(result); + r.write(result); } // DOM 2 // DOMString getAttributeNS(in DOMString namespaceURI, in DOMString localName); static void _getAttributeNS(Request& r, MethodParams& params) { + xmlChar* namespaceURI=as_xmlnsuri(r, params, 0); + xmlChar* localName=as_xmlname(r, params, 1); + VXnode& vnode=GET_SELF(r, VXnode); xmlNode& element=get_self_element(vnode); - xmlChar* namespaceURI=as_xmlchar(r, params, 0, "namespaceURI must be string"); - xmlChar* localName=as_xmlchar(r, params, 1, "localName must be string"); - // todo: when name="xmlns" xmlChar* attribute_value=xmlGetNsProp(&element, localName, namespaceURI); // write out result - r.write_pass_lang(r.transcode(attribute_value)); + r.write(r.transcode(attribute_value)); } // void setAttributeNS(in DOMString namespaceURI, in DOMString qualifiedName, in DOMString value) raises(DOMException); static void _setAttributeNS(Request& r, MethodParams& params) { + const xmlChar* namespaceURI=as_xmlnsuri(r, params, 0); + const xmlChar* qualifiedName=as_xmlqname(r, params, 1); + const xmlChar* attribute_value=as_xmlchar(r, params, 2, XML_VALUE_MUST_BE_STRING); + VXnode& vnode=GET_SELF(r, VXnode); xmlNode& element=get_self_element(vnode); VXdoc& vxdoc=vnode.get_vxdoc(); xmlDoc& xmldoc=vxdoc.get_xmldoc(); - const xmlChar* namespaceURI=as_xmlchar(r, params, 0, "namespaceURI must be string"); - const xmlChar* qualifiedName=as_xmlchar(r, params, 1, "qualifiedName must be string"); - const xmlChar* attribute_value=as_xmlchar(r, params, 2, "value must be string"); xmlChar* prefix=0; xmlChar* localName=xmlSplitQName2(qualifiedName, &prefix); - // todo: name=xmlns + // @todo: name=xmlns xmlAttr* attrNode; if(localName) { xmlNs& ns=pa_xmlMapNs(xmldoc, namespaceURI, prefix); @@ -519,30 +553,32 @@ static void _setAttributeNS(Request& r, } if(!attrNode) - throw XmlException(0); + throw XmlException(0, r); } // void removeAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException); static void _removeAttributeNS(Request& r, MethodParams& params) { + const xmlChar* namespaceURI=as_xmlnsuri(r, params, 0); + const xmlChar* localName=as_xmlname(r, params, 1); + VXnode& vnode=GET_SELF(r, VXnode); xmlNode& element=get_self_element(vnode); VXdoc& vxdoc=vnode.get_vxdoc(); xmlDoc& xmldoc=vxdoc.get_xmldoc(); - const xmlChar* namespaceURI=as_xmlchar(r, params, 0, "namespaceURI must be string"); - const xmlChar* localName=as_xmlchar(r, params, 1, "localName must be string"); - // todo: when name="xmlns" + // @todo: when name="xmlns" xmlNs& ns=pa_xmlMapNs(xmldoc, namespaceURI, 0); xmlUnsetNsProp(&element, &ns, localName); } // Attr getAttributeNodeNS(in DOMString namespaceURI, in DOMString localName); static void _getAttributeNodeNS(Request& r, MethodParams& params) { + const xmlChar* namespaceURI=as_xmlnsuri(r, params, 0); + const xmlChar* localName=as_xmlname(r, params, 1); + VXnode& vnode=GET_SELF(r, VXnode); VXdoc& vxdoc=vnode.get_vxdoc(); xmlNode& element=get_self_element(vnode); - const xmlChar* namespaceURI=as_xmlchar(r, params, 0, "namespaceURI must be string"); - const xmlChar* localName=as_xmlchar(r, params, 1, "localName must be string"); if(xmlNode* retNode=pa_getAttributeNodeNS(element, localName, namespaceURI)){ // write out result @@ -552,28 +588,26 @@ static void _getAttributeNodeNS(Request& // boolean hasAttribute(in DOMString name) raises(DOMException); static void _hasAttribute(Request& r, MethodParams& params) { + const xmlChar* name=as_xmlname(r, params, 0); + VXnode& vnode=GET_SELF(r, VXnode); xmlNode& element=get_self_element(vnode); - const xmlChar* name=as_xmlchar(r, params, 0, "name must be string"); - - xmlChar* prop=xmlGetProp(&element, name); - // todo: when name="xmlns" + // @todo: when name="xmlns" // write out result - r.write_no_lang(*new VBool(prop!=0)); + r.write(VBool::get(xmlHasProp(&element, name)!=0)); } // boolean hasAttributeNS(n DOMString namespaceURI, in DOMString localName) raises(DOMException); static void _hasAttributeNS(Request& r, MethodParams& params) { + const xmlChar* namespaceURI=as_xmlnsuri(r, params, 0); + const xmlChar* localName=as_xmlname(r, params, 1); + VXnode& vnode=GET_SELF(r, VXnode); xmlNode& element=get_self_element(vnode); - const xmlChar* namespaceURI=as_xmlchar(r, params, 0, "namespaceURI must be string"); - const xmlChar* localName=as_xmlchar(r, params, 1, "localName must be string"); - - xmlChar* prop=xmlGetNsProp(&element, localName, namespaceURI); // write out result - r.write_no_lang(*new VBool(prop!=0)); + r.write(VBool::get(xmlHasNsProp(&element, localName, namespaceURI)!=0)); } // boolean hasAttributes @@ -582,18 +616,23 @@ static void _hasAttributes(Request& r, M xmlNode& element=get_self_element(vnode); // write out result - r.write_no_lang(*new VBool(element.properties!=0)); + r.write(VBool::get(element.properties!=0)); } +// NodeList getElementsByTagNameNS(in DOMString namespaceURI, in DOMString localName); +// '*' as namespaceURI means get all namespaces +// '*' as localName means get all tags static void _getElementsByTagNameNS(Request& r, MethodParams& params) { + xmlChar* namespaceURI=as_xmlchar(r, params, 0, XML_NAMESPACEURI_MUST_BE_STRING); + + xmlChar* localName=as_xmlchar(r, params, 1, XML_LOCAL_NAME_MUST_BE_STRING); + if(xmlValidateName(localName, 0) != 0 && strcmp((const char*)localName, "*") != 0) + throw XmlException(0, XML_INVALID_LOCAL_NAME, localName); + VXnode& vnode=GET_SELF(r, VXnode); VXdoc& vdoc=vnode.get_vxdoc(); xmlDoc& xmldoc=vdoc.get_xmldoc(); - // namespaceURI;localName - xmlChar* namespaceURI=as_xmlchar(r, params, 0, "namespaceURI must be string"); - xmlChar* localName=as_xmlchar(r, params, 1, "name must be string"); - VHash& result=*new VHash; AccumulateFoundInfo info={&result.hash(), &vdoc, 0}; pa_xmlNamedPreorderTraversal((xmlNode*)&xmldoc, @@ -603,7 +642,7 @@ static void _getElementsByTagNameNS(Requ &info); // write out result - r.write_no_lang(result); + r.write(result); } @@ -663,13 +702,13 @@ static void _selectX(Request& r, MethodP xmlXPathEvalExpression(r.transcode(expression), ctxt.get())); if(xmlHaveGenericErrors()) - throw XmlException(0); + throw XmlException(0, r); Value* result=0; if(res.get()) handler(r, expression, res, vdoc, result); if(result) - r.write_no_lang(*result); + r.write(*result); } static void selectNodesHandler(Request&, @@ -708,7 +747,7 @@ static void selectNodeHandler(Request& r case XPATH_UNDEFINED: break; case XPATH_NODESET: - if(res->nodesetval && res->nodesetval->nodeNr) { // empty result strangly has NODESET res->type + if(res->nodesetval && res->nodesetval->nodeNr) { // empty result strangely has NODESET res->type if(res->nodesetval->nodeNr>1) throw Exception(PARSER_RUNTIME, &expression, @@ -718,7 +757,7 @@ static void selectNodeHandler(Request& r } break; case XPATH_BOOLEAN: - result=new VBool(res->boolval!=0); + result=&VBool::get(res->boolval!=0); break; case XPATH_NUMBER: result=new VDouble(res->floatval); @@ -740,7 +779,7 @@ static void selectBoolHandler(Request&, Value*& result) { switch(res->type) { case XPATH_BOOLEAN: - result=new VBool(res->boolval!=0); + result=&VBool::get(res->boolval!=0); break; case XPATH_NODESET: if(!(res->nodesetval && res->nodesetval->nodeNr)) @@ -826,9 +865,7 @@ static void _selectString(Request& r, Me // constructor /// @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) -{ +MXnode::MXnode(const char* aname): Methoded(aname?aname:"xnode") { /// DOM1 node // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException); @@ -900,10 +937,8 @@ MXnode::MXnode(const char* aname, VState // consts -#define CONST(name) \ - consts.put(String::Body(#name), new VInt(XML_##name)) -#define CONST2(name, value) \ - consts.put(String::Body(#name), new VInt(value)) +#define CONST(name) consts.put(#name, new VInt(XML_##name)) +#define CONST2(name, value) consts.put(#name, new VInt(value)) CONST(ELEMENT_NODE); CONST(ATTRIBUTE_NODE); @@ -919,10 +954,4 @@ MXnode::MXnode(const char* aname, VState CONST(NOTATION_NODE); } -#else - -// global variable - -DECLARE_CLASS_VAR(xnode, 0, 0); // fictive - #endif