|
|
| version 1.22, 2002/01/11 12:24:27 | version 1.35, 2002/01/28 10:50:03 |
|---|---|
| Line 12 | Line 12 |
| #include "pa_charset.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 "xnode.h" | #include "xnode.h" |
| extern "C" { | extern "C" { |
| #include "gdomecore/gdome-xml-node.h" | #include "gdomecore/gdome-xml-node.h" |
| }; | |
| #include "gdomecore/gdome-xml-document.h" | #include "gdomecore/gdome-xml-document.h" |
| }; | |
| #include "gdome.h" | #include "gdome.h" |
| #include "libxml/xpath.h" | #include "libxml/xpath.h" |
| // defines | |
| #define XNODE_CLASS_NAME "xnode" | |
| // classes | // classes |
| class xmlXPathObject_auto_ptr { | class xmlXPathObject_auto_ptr { |
| public: | public: |
| explicit xmlXPathObject_auto_ptr(xmlXPathObject *_P = 0) | explicit xmlXPathObject_auto_ptr(xmlXPathObject *_APtr = 0) |
| : _Owns(_P != 0), _Ptr(_P) {} | : _Owns(_APtr != 0), _Ptr(_APtr) {} |
| xmlXPathObject_auto_ptr(const xmlXPathObject_auto_ptr& _Y) | xmlXPathObject_auto_ptr(const xmlXPathObject_auto_ptr& _Y) |
| : _Owns(_Y._Owns), _Ptr(_Y.release()) {} | : _Owns(_Y._Owns), _Ptr(_Y.release()) {} |
| xmlXPathObject_auto_ptr& operator=(const xmlXPathObject_auto_ptr& _Y) | xmlXPathObject_auto_ptr& operator=(const xmlXPathObject_auto_ptr& _Y) |
| Line 59 private: | Line 65 private: |
| class xmlXPathContext_auto_ptr { | class xmlXPathContext_auto_ptr { |
| public: | public: |
| explicit xmlXPathContext_auto_ptr(xmlXPathContext *_P = 0) | explicit xmlXPathContext_auto_ptr(xmlXPathContext *_APtr = 0) |
| : _Owns(_P != 0), _Ptr(_P) {} | : _Owns(_APtr != 0), _Ptr(_APtr) {} |
| xmlXPathContext_auto_ptr(const xmlXPathContext_auto_ptr& _Y) | xmlXPathContext_auto_ptr(const xmlXPathContext_auto_ptr& _Y) |
| : _Owns(_Y._Owns), _Ptr(_Y.release()) {} | : _Owns(_Y._Owns), _Ptr(_Y.release()) {} |
| xmlXPathContext_auto_ptr& operator=(const xmlXPathContext_auto_ptr& _Y) | xmlXPathContext_auto_ptr& operator=(const xmlXPathContext_auto_ptr& _Y) |
| Line 90 private: | Line 96 private: |
| xmlXPathContext *_Ptr; | xmlXPathContext *_Ptr; |
| }; | }; |
| // defines | |
| #define XNODE_CLASS_NAME "xnode" | |
| // helpers | // helpers |
| GdomeNode *as_node(Pool& pool, const String& method_name, MethodParams *params, | GdomeNode *as_node(Pool& pool, const String& method_name, MethodParams *params, |
| int index, const char *msg) { | int index, const char *msg) { |
| Value& value=params->as_no_junction(index, msg); | Value& value=params->as_no_junction(index, msg); |
| if(strcmp(value.type(), VXNODE_TYPE)!=0) | if(strcmp(value.type(), VXNODE_TYPE)!=0 |
| || strcmp(value.type(), VXDOC_TYPE)!=0) | |
| throw Exception(0, 0, | throw Exception(0, 0, |
| &method_name, | &method_name, |
| msg); | msg); |
| Line 211 static void _hasChildNodes(Request& r, c | Line 214 static void _hasChildNodes(Request& r, c |
| } | } |
| // Node cloneNode(in boolean deep); | // Node cloneNode(in boolean deep); |
| /// @test ownerDocument=? | |
| static void _cloneNode(Request& r, const String& method_name, MethodParams *params) { | static void _cloneNode(Request& r, const String& method_name, MethodParams *params) { |
| Pool& pool=r.pool(); | Pool& pool=r.pool(); |
| VXnode& vnode=*static_cast<VXnode *>(r.self); | VXnode& vnode=*static_cast<VXnode *>(r.self); |
| Line 331 static void _removeAttributeNode(Request | Line 333 static void _removeAttributeNode(Request |
| gdome_el_removeAttributeNode(element, oldAttr, &exc); | gdome_el_removeAttributeNode(element, oldAttr, &exc); |
| if(exc) | if(exc) |
| throw Exception(0, 0, | throw Exception(0, 0, |
| &method_name, | &method_name, |
| exc); | exc); |
| } | } |
| // NodeList getElementsByTagName(in DOMString name); | // NodeList getElementsByTagName(in DOMString name); |
| Line 359 static void _getElementsByTagName(Reques | Line 361 static void _getElementsByTagName(Reques |
| } | } |
| } else if(exc) | } else if(exc) |
| throw Exception(0, 0, | throw Exception(0, 0, |
| &method_name, | &method_name, |
| exc); | exc); |
| // write out result | // write out result |
| r.write_no_lang(result); | r.write_no_lang(result); |
| Line 376 static void _normalize(Request& r, const | Line 378 static void _normalize(Request& r, const |
| gdome_n_normalize(selfNode, &exc); | gdome_n_normalize(selfNode, &exc); |
| if(exc) | if(exc) |
| throw Exception(0, 0, | throw Exception(0, 0, |
| &method_name, | &method_name, |
| exc); | exc); |
| } | } |
| /* | |
| static void _select(Request& r, const String& method_name, MethodParams *params) { | |
| // _asm int 3; | |
| Pool& pool=r.pool(); | |
| VXnode& vnode=*static_cast<VXnode *>(r.self); | |
| // expression | static void _selectX(Request& r, const String& method_name, MethodParams *params, |
| const String& expression=params->as_string(0, "expression must be string"); | void (*handler)(Pool& pool, |
| const char *expression_cstr=expression.cstr(); | const String& expression, |
| XalanDOMString dstring(expression_cstr); | xmlXPathObject_auto_ptr res, |
| const XalanDOMChar *expression_dcstr=dstring.c_str(); | Value *& result)) { |
| XPathEvaluator evaluator; | |
| // We'll use these to parse the XML file. | |
| XalanSourceTreeDOMSupport dom_support; | |
| try { | |
| NodeRefList list=evaluator.selectNodeList(dom_support, | |
| &vnode.get_node(&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(0).put(skey, new(pool) VXnode(pool, list.item(i), false)); | |
| } | |
| result.set_name(method_name); | |
| r.write_no_lang(result); | |
| } catch(const XSLException& e) { | |
| Exception::provide_source(pool, &expression, e); | |
| } | |
| } | |
| */ | |
| static void _selectSingle(Request& r, const String& method_name, MethodParams *params) { | |
| // _asm int 3; | // _asm int 3; |
| Pool& pool=r.pool(); | Pool& pool=r.pool(); |
| VXnode& vnode=*static_cast<VXnode *>(r.self); | VXnode& vnode=*static_cast<VXnode *>(r.self); |
| Line 429 static void _selectSingle(Request& r, co | Line 397 static void _selectSingle(Request& r, co |
| GdomeException exc; | GdomeException exc; |
| GdomeNode *dome_node=vnode.get_node(&method_name); | GdomeNode *dome_node=vnode.get_node(&method_name); |
| GdomeDocument *dome_document=gdome_n_ownerDocument(dome_node, &exc); | GdomeDocument *dome_document=gdome_n_ownerDocument(dome_node, &exc); |
| if(!dome_document) | if(!dome_document) // document does not own itself, so ownerDocument = 0 |
| dome_document=GDOME_DOC(dome_node); | dome_document=GDOME_DOC(dome_node); // and we need downcast |
| xmlDoc *xml_document=((_Gdome_xml_Document *)dome_document)->n; | xmlDoc *xml_document=gdome_xml_doc_get_xmlDoc(dome_document); |
| xmlXPathContext_auto_ptr ctxt(xmlXPathNewContext(xml_document)); | xmlXPathContext_auto_ptr ctxt(xmlXPathNewContext(xml_document)); |
| ctxt->node=xmlDocGetRootElement(xml_document); | ctxt->node=gdome_xml_n_get_xmlNode(dome_node); |
| /*error to stderr for now*/ | /*error to stderr for now*/ |
| xmlXPathObject_auto_ptr res( | xmlXPathObject_auto_ptr res( |
| xmlXPathEvalExpression(BAD_CAST pool.transcode(expression)->str, ctxt.get())); | xmlXPathEvalExpression(BAD_CAST pool.transcode(expression)->str, ctxt.get())); |
| if(xmlHaveGenericErrors()) { | |
| GdomeException exc=0; | |
| throw Exception(0, 0, | |
| &expression, | |
| exc); | |
| } | |
| Value *result=0; | |
| if(res.get()) | if(res.get()) |
| switch(res->type) { | handler(pool, expression, res, result); |
| case XPATH_UNDEFINED: break; | if(result) { |
| case XPATH_NODESET: | result->set_name(method_name); |
| { | r.write_no_lang(*result); |
| if(res->nodesetval->nodeNr>1) | } |
| throw Exception(0, 0, | } |
| &expression, | |
| "resulted not in a single node (%d)", res->nodesetval->nodeNr); | static void selectNodesHandler(Pool& pool, |
| const String& expression, | |
| VXnode& result=*new(pool) VXnode( | xmlXPathObject_auto_ptr res, |
| pool, | Value *& result) { |
| gdome_xml_n_mkref(res->nodesetval->nodeTab[0])); | VHash *vhash=new(pool) VHash(pool); result=vhash; |
| result.set_name(method_name); | switch(res->type) { |
| r.write_no_lang(result); | case XPATH_UNDEFINED: |
| break; | break; |
| case XPATH_NODESET: | |
| if(int size=res->nodesetval->nodeNr) { | |
| Hash& hash=vhash->hash(0); | |
| for(int i=0; i<size; i++) { | |
| String& skey=*new(pool) String(pool); | |
| { | |
| char *buf=(char *)pool.malloc(MAX_NUMBER); | |
| snprintf(buf, MAX_NUMBER, "%d", i); | |
| skey << buf; | |
| } | |
| hash.put(skey, new(pool) VXnode(pool, | |
| gdome_xml_n_mkref(res->nodesetval->nodeTab[i]))); | |
| } | } |
| //case XPATH_BOOLEAN: nothing; break; | } |
| //case XPATH_NUMBER: nothing; break; | break; |
| //case XPATH_STRING: nothing; break; | default: |
| default: | throw Exception(0, 0, |
| throw Exception(0, 0, | &expression, |
| "wrong xmlXPathEvalExpression result type (%d)", res->type); | |
| break; // never | |
| } | |
| } | |
| static void selectNodeHandler(Pool& pool, | |
| const String& expression, | |
| xmlXPathObject_auto_ptr res, | |
| Value *& result) { | |
| switch(res->type) { | |
| case XPATH_UNDEFINED: | |
| break; | |
| case XPATH_NODESET: | |
| if(res->nodesetval->nodeNr) { // empty result strangly has NODESET res->type | |
| if(res->nodesetval->nodeNr>1) | |
| throw Exception(0, 0, | |
| &expression, | &expression, |
| "unrecognized xmlXPathEvalExpression result type (%d)", res->type); | "resulted not in a single node (%d)", res->nodesetval->nodeNr); |
| break; // never | |
| result=new(pool) VXnode(pool, gdome_xml_n_mkref(res->nodesetval->nodeTab[0])); | |
| } | } |
| break; | |
| case XPATH_BOOLEAN: | |
| result=new(pool) VBool(pool, res->boolval!=0); | |
| break; | |
| case XPATH_NUMBER: | |
| result=new(pool) VDouble(pool, res->floatval); | |
| break; | |
| case XPATH_STRING: | |
| result=new(pool) VString( | |
| pool.transcode( | |
| GdomeDOMString_auto_ptr( | |
| gdome_str_mkref_dup((const gchar *)res->stringval)).get())); | |
| break; | |
| default: | |
| throw Exception(0, 0, | |
| &expression, | |
| "wrong xmlXPathEvalExpression result type (%d)", res->type); | |
| break; // never | |
| } | |
| } | |
| static void selectBoolHandler(Pool& pool, | |
| const String& expression, | |
| xmlXPathObject_auto_ptr res, | |
| Value *& result) { | |
| switch(res->type) { | |
| case XPATH_BOOLEAN: | |
| result=new(pool) VBool(pool, res->boolval!=0); | |
| break; | |
| case XPATH_NODESET: | |
| if(!res->nodesetval->nodeNr) | |
| break; | |
| // else[nodeset] fall down to default | |
| default: | |
| throw Exception(0, 0, | |
| &expression, | |
| "wrong xmlXPathEvalExpression result type (%d)", res->type); | |
| break; // never | |
| } | |
| } | |
| static void selectNumberHandler(Pool& pool, | |
| const String& expression, | |
| xmlXPathObject_auto_ptr res, | |
| Value *& result) { | |
| switch(res->type) { | |
| case XPATH_NUMBER: | |
| result=new(pool) VDouble(pool, res->floatval); | |
| break; | |
| case XPATH_NODESET: | |
| if(!res->nodesetval->nodeNr) | |
| break; | |
| // else[nodeset] fall down to default | |
| default: | |
| throw Exception(0, 0, | |
| &expression, | |
| "wrong xmlXPathEvalExpression result type (%d)", res->type); | |
| break; // never | |
| } | |
| } | |
| static void selectStringHandler(Pool& pool, | |
| const String& expression, | |
| xmlXPathObject_auto_ptr res, | |
| Value *& result) { | |
| switch(res->type) { | |
| case XPATH_UNDEFINED: | |
| break; | |
| case XPATH_STRING: | |
| result=new(pool) VString( | |
| pool.transcode( | |
| GdomeDOMString_auto_ptr( | |
| gdome_str_mkref_dup((const gchar *)res->stringval)).get())); | |
| break; | |
| case XPATH_NODESET: | |
| if(!res->nodesetval->nodeNr) | |
| break; | |
| // else[nodeset] fall down to default | |
| default: | |
| throw Exception(0, 0, | |
| &expression, | |
| "wrong xmlXPathEvalExpression result type (%d)", res->type); | |
| break; // never | |
| } | |
| } | |
| static void _select(Request& r, const String& method_name, MethodParams *params) { | |
| _selectX(r, method_name, params, | |
| selectNodesHandler); | |
| } | |
| static void _selectSingle(Request& r, const String& method_name, MethodParams *params) { | |
| _selectX(r, method_name, params, | |
| selectNodeHandler); | |
| } | |
| static void _selectBool(Request& r, const String& method_name, MethodParams *params) { | |
| _selectX(r, method_name, params, | |
| selectBoolHandler); | |
| } | |
| static void _selectNumber(Request& r, const String& method_name, MethodParams *params) { | |
| _selectX(r, method_name, params, | |
| selectNumberHandler); | |
| } | |
| static void _selectString(Request& r, const String& method_name, MethodParams *params) { | |
| _selectX(r, method_name, params, | |
| selectStringHandler); | |
| } | } |
| // constructor | // constructor |
| Line 508 MXnode::MXnode(Pool& apool) : Methoded(a | Line 623 MXnode::MXnode(Pool& apool) : Methoded(a |
| /// parser | /// 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, _selectSingle, 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 |