Annotation of parser3/src/classes/xnode.C, revision 1.66
1.1 parser 1: /** @file
2: Parser: @b dom parser class.
3:
1.65 paf 4: Copyright (c) 2001-2004 ArtLebedev Group (http://www.artlebedev.com)
1.38 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.1 parser 6: */
7: #include "classes.h"
8: #ifdef XML
1.46 paf 9:
1.66 ! paf 10: static const char * const IDENT_XNODE_C="$Date: 2004/02/11 15:33:13 $";
1.56 paf 11:
12: #include "pa_vmethod_frame.h"
1.1 parser 13:
1.21 paf 14: #include "pa_charset.h"
1.1 parser 15: #include "pa_request.h"
16: #include "pa_vxnode.h"
1.34 paf 17: #include "pa_vxdoc.h"
1.23 paf 18: #include "pa_vvoid.h"
1.60 paf 19: #include "pa_xml_exception.h"
1.1 parser 20:
21: #include "xnode.h"
22:
1.21 paf 23: extern "C" {
24: #include "gdomecore/gdome-xml-node.h"
1.27 paf 25: #include "gdomecore/gdome-xml-document.h"
1.21 paf 26: };
1.19 paf 27: #include "gdome.h"
1.21 paf 28: #include "libxml/xpath.h"
1.66 ! paf 29: #include "libxml/xpathInternals.h"
1.21 paf 30:
1.56 paf 31: // global variable
32:
33: DECLARE_CLASS_VAR(xnode, new MXnode, 0);
34:
1.21 paf 35: // classes
36:
37: class xmlXPathObject_auto_ptr {
38: public:
1.29 paf 39: explicit xmlXPathObject_auto_ptr(xmlXPathObject *_APtr = 0)
40: : _Owns(_APtr != 0), _Ptr(_APtr) {}
1.21 paf 41: xmlXPathObject_auto_ptr(const xmlXPathObject_auto_ptr& _Y)
42: : _Owns(_Y._Owns), _Ptr(_Y.release()) {}
43: xmlXPathObject_auto_ptr& operator=(const xmlXPathObject_auto_ptr& _Y)
44: {if (this != &_Y)
45: {if (_Ptr != _Y.get())
46: {if (_Owns && _Ptr)
47: xmlXPathFreeObject(_Ptr);
48: _Owns = _Y._Owns; }
49: else if (_Y._Owns)
50: _Owns = true;
51: _Ptr = _Y.release(); }
52: return (*this); }
53: ~xmlXPathObject_auto_ptr()
54: {if (_Owns && _Ptr)
55: xmlXPathFreeObject(_Ptr); }
56: xmlXPathObject& operator*() const
57: {return (*get()); }
58: xmlXPathObject *operator->() const
59: {return (get()); }
60: xmlXPathObject *get() const
61: {return (_Ptr); }
62: xmlXPathObject *release() const
63: {((xmlXPathObject_auto_ptr *)this)->_Owns = false;
64: return (_Ptr); }
65: private:
66: bool _Owns;
67: xmlXPathObject *_Ptr;
68: };
69:
70: class xmlXPathContext_auto_ptr {
71: public:
1.29 paf 72: explicit xmlXPathContext_auto_ptr(xmlXPathContext *_APtr = 0)
73: : _Owns(_APtr != 0), _Ptr(_APtr) {}
1.21 paf 74: xmlXPathContext_auto_ptr(const xmlXPathContext_auto_ptr& _Y)
75: : _Owns(_Y._Owns), _Ptr(_Y.release()) {}
76: xmlXPathContext_auto_ptr& operator=(const xmlXPathContext_auto_ptr& _Y)
77: {if (this != &_Y)
78: {if (_Ptr != _Y.get())
79: {if (_Owns && _Ptr)
80: xmlXPathFreeContext(_Ptr);
81: _Owns = _Y._Owns; }
82: else if (_Y._Owns)
83: _Owns = true;
84: _Ptr = _Y.release(); }
85: return (*this); }
86: ~xmlXPathContext_auto_ptr()
87: {if (_Owns && _Ptr)
88: xmlXPathFreeContext(_Ptr); }
89: xmlXPathContext& operator*() const
90: {return (*get()); }
91: xmlXPathContext *operator->() const
92: {return (get()); }
93: xmlXPathContext *get() const
94: {return (_Ptr); }
95: xmlXPathContext *release() const
96: {((xmlXPathContext_auto_ptr *)this)->_Owns = false;
97: return (_Ptr); }
98: private:
99: bool _Owns;
100: xmlXPathContext *_Ptr;
101: };
1.1 parser 102:
1.6 parser 103: // helpers
104:
1.56 paf 105: GdomeNode* as_node(MethodParams& params,
106: int index, const char* msg) {
107: GdomeNode* result;
108: Value& value=params.as_no_junction(index, msg);
109: if(Value* vxnode=value.as(VXNODE_TYPE, false))
110: result=static_cast<VXnode*>(vxnode)->get_node();
111: else {
1.41 paf 112: throw Exception("parser.runtime",
1.56 paf 113: 0,
1.6 parser 114: msg);
1.56 paf 115: }
116:
117: return result;
1.6 parser 118: }
119:
120: // helpers
121:
1.56 paf 122: GdomeAttr* as_attr(MethodParams& params,
123: int index, const char* msg) {
124: GdomeNode* node=as_node(params, index, msg);
1.19 paf 125: GdomeException exc;
126: if(gdome_n_nodeType(node, &exc)!=GDOME_ATTRIBUTE_NODE)
1.41 paf 127: throw Exception("parser.runtime",
1.56 paf 128: 0,
1.6 parser 129: msg);
130:
1.19 paf 131: return GDOME_A(node);
1.6 parser 132: }
1.1 parser 133:
134: // methods
135:
1.6 parser 136: // DOM1 node
137:
138: // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException);
1.56 paf 139: static void _insertBefore(Request& r, MethodParams& params) {
140: VXnode& vnode=GET_SELF(r, VXnode);
141: GdomeNode* selfNode=vnode.get_node();
142: GdomeNode* newChild=as_node(params, 0, "newChild must be node");
143: GdomeNode* refChild=as_node(params, 1, "refChild must be node");
1.6 parser 144:
1.19 paf 145: GdomeException exc;
1.56 paf 146: if(GdomeNode* retNode=gdome_n_insertBefore(selfNode, newChild, refChild, &exc)) {
1.19 paf 147: // write out result
1.56 paf 148: r.write_no_lang(*new VXnode(&r.charsets, retNode));
1.19 paf 149: } else
1.60 paf 150: throw XmlException(0, exc);
1.6 parser 151: }
152:
153: // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException);
1.56 paf 154: static void _replaceChild(Request& r, MethodParams& params) {
155: VXnode& vnode=GET_SELF(r, VXnode);
156: GdomeNode* selfNode=vnode.get_node();
157: GdomeNode* newChild=as_node(params, 0, "newChild must be node");
1.61 paf 158: GdomeNode* oldChild=as_node(params, 1, "oldChild must be node");
1.6 parser 159:
1.19 paf 160: GdomeException exc;
1.61 paf 161: if(GdomeNode* retNode=gdome_n_replaceChild(selfNode, newChild, oldChild, &exc)) {
1.19 paf 162: // write out result
1.56 paf 163: r.write_no_lang(*new VXnode(&r.charsets, retNode));
1.19 paf 164: } else
1.60 paf 165: throw XmlException(0, exc);
1.6 parser 166: }
167:
168: // Node removeChild(in Node oldChild) raises(DOMException);
1.56 paf 169: static void _removeChild(Request& r, MethodParams& params) {
170: VXnode& vnode=GET_SELF(r, VXnode);
171: GdomeNode* selfNode=vnode.get_node();
172: GdomeNode* oldChild=as_node(params, 0, "oldChild must be node");
1.6 parser 173:
1.19 paf 174: GdomeException exc;
1.56 paf 175: if(GdomeNode* retNode=gdome_n_removeChild(selfNode, oldChild, &exc)) {
1.19 paf 176: // write out result
1.56 paf 177: r.write_no_lang(*new VXnode(&r.charsets, retNode));
1.19 paf 178: } else
1.60 paf 179: throw XmlException(0, exc);
1.6 parser 180: }
181:
182: // Node appendChild(in Node newChild) raises(DOMException);
1.56 paf 183: static void _appendChild(Request& r, MethodParams& params) {
184: VXnode& vnode=GET_SELF(r, VXnode);
185: GdomeNode* selfNode=vnode.get_node();
186: GdomeNode* newChild=as_node(params, 0, "newChild must be node");
1.6 parser 187:
1.19 paf 188: GdomeException exc;
1.56 paf 189: if(GdomeNode* retNode=gdome_n_appendChild(selfNode, newChild, &exc)) {
1.19 paf 190: // write out result
1.56 paf 191: r.write_no_lang(*new VXnode(&r.charsets, retNode));
1.19 paf 192: } else
1.60 paf 193: throw XmlException(0, exc);
1.6 parser 194: }
195:
196: // boolean hasChildNodes();
1.56 paf 197: static void _hasChildNodes(Request& r, MethodParams&) {
198: VXnode& vnode=GET_SELF(r, VXnode);
199: GdomeNode* node=vnode.get_node();
1.6 parser 200:
1.19 paf 201: GdomeException exc;
1.6 parser 202: // write out result
1.44 paf 203: bool result=gdome_n_hasChildNodes(node, &exc)!=0;
1.56 paf 204: r.write_no_lang(*new VBool(result));
1.6 parser 205: }
206:
207: // Node cloneNode(in boolean deep);
1.56 paf 208: static void _cloneNode(Request& r, MethodParams& params) {
209: VXnode& vnode=GET_SELF(r, VXnode);
210: GdomeNode* node=vnode.get_node();
1.6 parser 211:
1.56 paf 212: bool deep=params.as_bool(0, "deep must be bool", r);
1.6 parser 213:
1.19 paf 214: GdomeException exc;
1.6 parser 215: // write out result
1.56 paf 216: r.write_no_lang(*new VXnode(&r.charsets, gdome_n_cloneNode(node, deep, &exc)));
1.6 parser 217: }
218:
219: // DOM1 element
220:
1.56 paf 221: GdomeElement* get_self_element(Request& r) {
222: VXnode& vnode=GET_SELF(r, VXnode);
223: GdomeNode* node=vnode.get_node();
1.6 parser 224:
1.19 paf 225: GdomeException exc;
1.50 paf 226: if(gdome_n_nodeType(node, &exc)!=GDOME_ELEMENT_NODE)
1.41 paf 227: throw Exception("parser.runtime",
1.56 paf 228: 0,
1.51 paf 229: "method can only be called on nodes of ELEMENT type");
1.6 parser 230:
1.19 paf 231: return GDOME_EL(node);
1.6 parser 232: }
233:
1.56 paf 234:
235:
1.64 paf 236: /// @bug attribute_value must be freed! [// DOMString getAttribute(in DOMString name);
1.56 paf 237: static void _getAttribute(Request& r, MethodParams& params) {
238: GdomeElement* element=get_self_element(r);
239: const String& name=params.as_string(0, "name must be string");
1.6 parser 240:
1.19 paf 241: GdomeException exc;
242: GdomeDOMString *attribute_value=
1.56 paf 243: gdome_el_getAttribute(element, r.transcode(name).use(), &exc);
1.6 parser 244: // write out result
1.56 paf 245: r.write_no_lang(r.transcode(attribute_value));
1.6 parser 246: }
247:
248: // void setAttribute(in DOMString name, in DOMString value) raises(DOMException);
1.56 paf 249: static void _setAttribute(Request& r, MethodParams& params) {
250: GdomeElement* element=get_self_element(r);
251: const String& name=params.as_string(0, "name must be string");
252: const String& attribute_value=params.as_string(1, "value must be string");
1.6 parser 253:
1.19 paf 254: GdomeException exc;
255: gdome_el_setAttribute(element,
1.56 paf 256: r.transcode(name).use(),
257: r.transcode(attribute_value).use(),
1.19 paf 258: &exc);
259: if(exc)
1.60 paf 260: throw XmlException(0, exc);
1.6 parser 261: }
262:
263: // void removeAttribute(in DOMString name) raises(DOMException);
1.56 paf 264: static void _removeAttribute(Request& r, MethodParams& params) {
265: GdomeElement* element=get_self_element(r);
266: const String& name=params.as_string(0, "name must be string");
1.6 parser 267:
1.19 paf 268: GdomeException exc;
1.56 paf 269: gdome_el_removeAttribute(element, r.transcode(name).use(), &exc);
1.19 paf 270: if(exc)
1.60 paf 271: throw XmlException(0, exc);
1.6 parser 272: }
273:
274: // Attr getAttributeNode(in DOMString name);
1.56 paf 275: static void _getAttributeNode(Request& r, MethodParams& params) {
276: GdomeElement* element=get_self_element(r);
277: const String& name=params.as_string(0, "name must be string");
1.6 parser 278:
1.19 paf 279: GdomeException exc;
1.56 paf 280: if(GdomeAttr *attr=gdome_el_getAttributeNode(element,
281: r.transcode(name).use(), &exc)) {
1.6 parser 282: // write out result
1.56 paf 283: r.write_no_lang(*new VXnode(&r.charsets, (GdomeNode* )attr));
1.19 paf 284: } else if(exc)
1.60 paf 285: throw XmlException(0, exc);
1.6 parser 286: }
287:
288: // Attr setAttributeNode(in Attr newAttr) raises(DOMException);
1.56 paf 289: static void _setAttributeNode(Request& r, MethodParams& params) {
290: GdomeElement* element=get_self_element(r);
291: GdomeAttr * newAttr=as_attr(params, 0, "newAttr must be ATTRIBUTE node");
1.6 parser 292:
1.19 paf 293: GdomeException exc;
294: if(GdomeAttr *returnAttr=gdome_el_setAttributeNode(element, newAttr, &exc)) {
295: // write out result
1.56 paf 296: r.write_no_lang(*new VXnode(&r.charsets, (GdomeNode* )returnAttr));
1.19 paf 297: } else
1.60 paf 298: throw XmlException(0, exc);
1.6 parser 299: }
300:
301: // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException);
1.56 paf 302: static void _removeAttributeNode(Request& r, MethodParams& params) {
303: GdomeElement* element=get_self_element(r);
304: GdomeAttr * oldAttr=as_attr(params, 0, "oldAttr must be ATTRIBUTE node");
1.6 parser 305:
1.19 paf 306: GdomeException exc;
307: gdome_el_removeAttributeNode(element, oldAttr, &exc);
308: if(exc)
1.60 paf 309: throw XmlException(0, exc);
1.6 parser 310: }
311:
312: // NodeList getElementsByTagName(in DOMString name);
1.56 paf 313: static void _getElementsByTagName(Request& r, MethodParams& params) {
314: GdomeElement* element=get_self_element(r);
1.6 parser 315:
1.56 paf 316: const String& name=params.as_string(0, "name must be string");
1.6 parser 317:
1.56 paf 318: VHash& result=*new VHash;
1.19 paf 319: GdomeException exc;
320: if(GdomeNodeList *nodes=
1.56 paf 321: gdome_el_getElementsByTagName(element, r.transcode(name).use(), &exc)) {
1.19 paf 322: gulong length=gdome_nl_length(nodes, &exc);
1.56 paf 323: for(gulong i=0; i<length; i++)
324: result.hash().put(
1.59 paf 325: String::Body::Format(i),
1.56 paf 326: new VXnode(&r.charsets, gdome_nl_item(nodes, i, &exc)));
1.19 paf 327: } else if(exc)
1.60 paf 328: throw XmlException(0, exc);
1.6 parser 329:
330: // write out result
331: r.write_no_lang(result);
332: }
333:
1.57 paf 334: // DOM 2
335:
1.58 paf 336: // DOMString getAttributeNS(in DOMString namespaceURI, in DOMString localName);
1.57 paf 337: static void _getAttributeNS(Request& r, MethodParams& params) {
338: GdomeElement* element=get_self_element(r);
339:
340: const String& namespaceURI=params.as_string(0, "namespaceURI must be string");
341: const String& localName=params.as_string(0, "localName must be string");
342:
343: GdomeException exc;
344: GdomeDOMString *attribute_value=
345: gdome_el_getAttributeNS(element,
346: r.transcode(namespaceURI).use(),
347: r.transcode(localName).use(), &exc);
348: // write out result
349: r.write_no_lang(r.transcode(attribute_value));
350: }
351:
1.58 paf 352: // void setAttributeNS(in DOMString namespaceURI, in DOMString qualifiedName, in DOMString value) raises(DOMException);
1.57 paf 353: static void _setAttributeNS(Request& r, MethodParams& params) {
354: GdomeElement* element=get_self_element(r);
355: const String& namespaceURI=params.as_string(0, "namespaceURI must be string");
356: const String& qualifiedName=params.as_string(1, "qualifiedName must be string");
357: const String& attribute_value=params.as_string(2, "value must be string");
358:
359: GdomeException exc;
360: gdome_el_setAttributeNS(element,
361: r.transcode(namespaceURI).use(),
362: r.transcode(qualifiedName).use(),
363: r.transcode(attribute_value).use(),
364: &exc);
365: if(exc)
1.60 paf 366: throw XmlException(0, exc);
1.57 paf 367: }
368:
1.58 paf 369: // void removeAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException);
1.57 paf 370: static void _removeAttributeNS(Request& r, MethodParams& params) {
371: GdomeElement* element=get_self_element(r);
372: const String& namespaceURI=params.as_string(0, "namespaceURI must be string");
373: const String& localName=params.as_string(1, "localName must be string");
374:
375: GdomeException exc;
376: gdome_el_removeAttributeNS(element,
377: r.transcode(namespaceURI).use(),
378: r.transcode(localName).use(),
379: &exc);
380: if(exc)
1.60 paf 381: throw XmlException(0, exc);
1.57 paf 382: }
383:
1.58 paf 384: // Attr getAttributeNodeNS(in DOMString namespaceURI, in DOMString localName);
1.57 paf 385: static void _getAttributeNodeNS(Request& r, MethodParams& params) {
386: GdomeElement* element=get_self_element(r);
387: const String& namespaceURI=params.as_string(0, "namespaceURI must be string");
388: const String& name=params.as_string(1, "name must be string");
389:
390: GdomeException exc;
391: if(GdomeAttr *attr=gdome_el_getAttributeNodeNS(element,
392: r.transcode(namespaceURI).use(), r.transcode(name).use(), &exc)) {
393: // write out result
394: r.write_no_lang(*new VXnode(&r.charsets, (GdomeNode* )attr));
395: } else if(exc)
1.60 paf 396: throw XmlException(0, exc);
1.57 paf 397: }
398:
399: // Attr setAttributeNodeNS(in Attr newAttr) raises(DOMException);
400: static void _setAttributeNodeNS(Request& r, MethodParams& params) {
401: GdomeElement* element=get_self_element(r);
402: GdomeAttr * newAttr=as_attr(params, 0, "newAttr must be ATTRIBUTE node");
403:
404: GdomeException exc;
405: if(GdomeAttr *returnAttr=gdome_el_setAttributeNodeNS(element, newAttr, &exc)) {
406: // write out result
407: r.write_no_lang(*new VXnode(&r.charsets, (GdomeNode* )returnAttr));
408: } else
1.60 paf 409: throw XmlException(0, exc);
1.57 paf 410: }
411:
1.58 paf 412: // boolean hasAttribute(in DOMString name) raises(DOMException);
1.57 paf 413: static void _hasAttribute(Request& r, MethodParams& params) {
414: GdomeElement* element=get_self_element(r);
415:
416: const String& name=params.as_string(0, "name must be string");
417:
418: GdomeException exc;
419: // write out result
420: bool result=gdome_el_hasAttribute(element,
421: r.transcode(name).use(),
422: &exc)!=0;
423: r.write_no_lang(*new VBool(result));
424: }
425:
1.58 paf 426: // boolean hasAttributeNS(n DOMString namespaceURI, in DOMString localName) raises(DOMException);
1.57 paf 427: static void _hasAttributeNS(Request& r, MethodParams& params) {
428: GdomeElement* element=get_self_element(r);
429:
430: const String& namespaceURI=params.as_string(0, "namespaceURI must be string");
431: const String& localName=params.as_string(1, "localName must be string");
432:
433: GdomeException exc;
434: // write out result
435: bool result=gdome_el_hasAttributeNS(element,
436: r.transcode(namespaceURI).use(),
437: r.transcode(localName).use(),
438: &exc)!=0;
439: r.write_no_lang(*new VBool(result));
440: }
441:
1.56 paf 442: static void _getElementsByTagNameNS(Request& r, MethodParams& params) {
443: GdomeElement* element=get_self_element(r);
1.39 paf 444:
445: // namespaceURI;localName
1.56 paf 446: const String& namespaceURI=params.as_string(0, "namespaceURI must be string");
447: const String& localName=params.as_string(1, "localName must be string");
1.39 paf 448:
449: GdomeException exc;
1.56 paf 450: VHash& result=*new VHash;
1.39 paf 451: if(GdomeNodeList *nodes=
452: gdome_el_getElementsByTagNameNS(
453: element,
1.56 paf 454: r.transcode(namespaceURI).use(),
455: r.transcode(localName).use(),
1.39 paf 456: &exc)) {
457: gulong length=gdome_nl_length(nodes, &exc);
1.56 paf 458: for(gulong i=0; i<length; i++)
459: result.hash().put(
1.59 paf 460: String::Body::Format(i),
1.56 paf 461: new VXnode(&r.charsets, gdome_nl_item(nodes, i, &exc)));
1.39 paf 462: }
463:
464: // write out result
465: r.write_no_lang(result);
466: }
467:
1.6 parser 468: // void normalize();
1.56 paf 469: static void _normalize(Request& r, MethodParams&) {
470: VXnode& vnode=GET_SELF(r, VXnode);
471: GdomeNode* selfNode=vnode.get_node();
1.6 parser 472:
1.19 paf 473: GdomeException exc;
474: gdome_n_normalize(selfNode, &exc);
475: if(exc)
1.60 paf 476: throw XmlException(0, exc);
1.6 parser 477: }
1.25 paf 478:
1.66 ! paf 479: #ifndef DOXYGEN
! 480: struct Register_one_ns_info {
! 481: Request* r;
! 482: xmlXPathContextPtr ctxt;
! 483: };
! 484: #endif
! 485: static void register_one_ns(
! 486: HashStringValue::key_type key,
! 487: HashStringValue::value_type value,
! 488: Register_one_ns_info* info) {
! 489: if(const String* svalue=value->get_string())
! 490: xmlXPathRegisterNs(info->ctxt,
! 491: BAD_CAST info->r->transcode(key)->str,
! 492: BAD_CAST info->r->transcode(*svalue)->str);
! 493: else
! 494: throw Exception("parser.runtime",
! 495: new String(key, String::L_TAINTED),
! 496: "value is %s, must be string or number", value->type());
! 497: }
1.56 paf 498: static void _selectX(Request& r, MethodParams& params,
499: void (*handler)(Request& r,
1.26 paf 500: const String& expression,
501: xmlXPathObject_auto_ptr res,
1.56 paf 502: Value*& result)) {
503: VXnode& vnode=GET_SELF(r, VXnode);
1.1 parser 504:
505: // expression
1.56 paf 506: const String& expression=params.as_string(0, "expression must be string");
1.66 ! paf 507: HashStringValue* namespaces=0;
! 508: if(params.count()>1) {
! 509: Value* vnamespaces=params.get(1);
! 510: namespaces=vnamespaces->get_hash();
! 511: if(!namespaces && !vnamespaces->is_string())
! 512: throw Exception("parser.runtime",
! 513: 0,
! 514: "namespaces parameter must be hash");
! 515: }
1.1 parser 516:
1.25 paf 517: GdomeException exc;
1.56 paf 518: GdomeNode* dome_node=vnode.get_node();
1.25 paf 519: GdomeDocument *dome_document=gdome_n_ownerDocument(dome_node, &exc);
1.32 paf 520: if(!dome_document) // document does not own itself, so ownerDocument = 0
521: dome_document=GDOME_DOC(dome_node); // and we need downcast
1.33 paf 522: xmlDoc *xml_document=gdome_xml_doc_get_xmlDoc(dome_document);
1.56 paf 523: xmlXPathContext_auto_ptr ctxt(xmlXPathNewContext(xml_document));
1.66 ! paf 524: if(namespaces) {
! 525: Register_one_ns_info info={&r, ctxt.get()};
! 526: namespaces->for_each(register_one_ns, &info);
! 527: }
1.32 paf 528: ctxt->node=gdome_xml_n_get_xmlNode(dome_node);
1.25 paf 529: /*error to stderr for now*/
530: xmlXPathObject_auto_ptr res(
1.56 paf 531: xmlXPathEvalExpression(BAD_CAST r.transcode(expression)->str, ctxt.get()));
1.28 paf 532:
533: if(xmlHaveGenericErrors()) {
534: GdomeException exc=0;
1.60 paf 535: throw XmlException(&expression, exc);
1.28 paf 536: }
1.25 paf 537:
1.56 paf 538: Value* result=0;
1.25 paf 539: if(res.get())
1.56 paf 540: handler(r, expression, res, result);
1.44 paf 541: if(result)
1.26 paf 542: r.write_no_lang(*result);
543: }
1.25 paf 544:
1.56 paf 545: static void selectNodesHandler(Request& r,
546: const String& expression,
547: xmlXPathObject_auto_ptr res,
548: Value*& result) {
549: VHash& vhash=*new VHash; result=&vhash;
1.26 paf 550: switch(res->type) {
551: case XPATH_UNDEFINED:
552: break;
553: case XPATH_NODESET:
1.40 paf 554: if(res->nodesetval)
555: if(int size=res->nodesetval->nodeNr) {
1.56 paf 556: HashStringValue& hash=vhash.hash();
557: for(int i=0; i<size; i++)
558: hash.put(
1.59 paf 559: String::Body::Format(i),
1.56 paf 560: new VXnode(
561: &r.charsets,
562: gdome_xml_n_mkref(res->nodesetval->nodeTab[i])));
1.1 parser 563: }
1.26 paf 564: break;
565: default:
1.41 paf 566: throw Exception(0,
1.26 paf 567: &expression,
568: "wrong xmlXPathEvalExpression result type (%d)", res->type);
569: break; // never
570: }
571: }
572:
1.56 paf 573: static void selectNodeHandler(Request& r,
574: const String& expression,
575: xmlXPathObject_auto_ptr res,
576: Value*& result) {
1.26 paf 577: switch(res->type) {
578: case XPATH_UNDEFINED:
579: break;
580: case XPATH_NODESET:
1.40 paf 581: if(res->nodesetval && res->nodesetval->nodeNr) { // empty result strangly has NODESET res->type
1.26 paf 582: if(res->nodesetval->nodeNr>1)
1.41 paf 583: throw Exception("parser.runtime",
1.56 paf 584: &expression,
585: "resulted not in a single node (%d)", res->nodesetval->nodeNr);
1.26 paf 586:
1.56 paf 587: result=new VXnode(
588: &r.charsets,
589: gdome_xml_n_mkref(res->nodesetval->nodeTab[0]));
1.25 paf 590: }
1.26 paf 591: break;
592: case XPATH_BOOLEAN:
1.56 paf 593: result=new VBool(res->boolval!=0);
1.26 paf 594: break;
595: case XPATH_NUMBER:
1.56 paf 596: result=new VDouble(res->floatval);
1.26 paf 597: break;
598: case XPATH_STRING:
1.56 paf 599: result=new VString(r.transcode((xmlChar*)res->stringval));
1.26 paf 600: break;
601: default:
1.41 paf 602: throw Exception("parser.runtime",
1.26 paf 603: &expression,
604: "wrong xmlXPathEvalExpression result type (%d)", res->type);
1.56 paf 605: // result=0;
1.26 paf 606: break; // never
607: }
608: }
609:
1.62 paf 610: static void selectBoolHandler(Request&,
1.56 paf 611: const String& expression,
612: xmlXPathObject_auto_ptr res,
613: Value*& result) {
1.26 paf 614: switch(res->type) {
615: case XPATH_BOOLEAN:
1.56 paf 616: result=new VBool(res->boolval!=0);
1.26 paf 617: break;
618: case XPATH_NODESET:
1.40 paf 619: if(!(res->nodesetval && res->nodesetval->nodeNr))
1.26 paf 620: break;
621: // else[nodeset] fall down to default
622: default:
1.41 paf 623: throw Exception("parser.runtime",
1.26 paf 624: &expression,
625: "wrong xmlXPathEvalExpression result type (%d)", res->type);
626: break; // never
627: }
628: }
1.1 parser 629:
1.62 paf 630: static void selectNumberHandler(Request&,
1.56 paf 631: const String& expression,
632: xmlXPathObject_auto_ptr res,
633: Value*& result) {
1.26 paf 634: switch(res->type) {
635: case XPATH_NUMBER:
1.56 paf 636: result=new VDouble(res->floatval);
1.26 paf 637: break;
638: case XPATH_NODESET:
1.40 paf 639: if(!(res->nodesetval && res->nodesetval->nodeNr))
1.26 paf 640: break;
641: // else[nodeset] fall down to default
642: default:
1.41 paf 643: throw Exception("parser.runtime",
1.26 paf 644: &expression,
645: "wrong xmlXPathEvalExpression result type (%d)", res->type);
646: break; // never
647: }
648: }
649:
1.56 paf 650: static void selectStringHandler(Request& r,
1.26 paf 651: const String& expression,
652: xmlXPathObject_auto_ptr res,
1.56 paf 653: Value*& result) {
1.26 paf 654: switch(res->type) {
655: case XPATH_UNDEFINED:
656: break;
657: case XPATH_STRING:
1.56 paf 658: result=new VString(r.transcode((xmlChar*)res->stringval));
1.26 paf 659: break;
660: case XPATH_NODESET:
1.40 paf 661: if(!(res->nodesetval && res->nodesetval->nodeNr))
1.26 paf 662: break;
663: // else[nodeset] fall down to default
664: default:
1.41 paf 665: throw Exception("parser.runtime",
1.26 paf 666: &expression,
667: "wrong xmlXPathEvalExpression result type (%d)", res->type);
668: break; // never
1.1 parser 669: }
670: }
1.25 paf 671:
1.56 paf 672: static void _select(Request& r, MethodParams& params) {
673: _selectX(r, params,
1.26 paf 674: selectNodesHandler);
675: }
676:
1.56 paf 677: static void _selectSingle(Request& r, MethodParams& params) {
678: _selectX(r, params,
1.26 paf 679: selectNodeHandler);
680: }
1.1 parser 681:
1.56 paf 682: static void _selectBool(Request& r, MethodParams& params) {
683: _selectX(r, params,
1.26 paf 684: selectBoolHandler);
685: }
1.20 paf 686:
1.56 paf 687: static void _selectNumber(Request& r, MethodParams& params) {
688: _selectX(r, params,
1.26 paf 689: selectNumberHandler);
690: }
1.24 paf 691:
1.56 paf 692: static void _selectString(Request& r, MethodParams& params) {
693: _selectX(r, params,
1.26 paf 694: selectStringHandler);
1.1 parser 695: }
1.20 paf 696:
1.1 parser 697: // constructor
698:
1.56 paf 699: /// @bug one can change const and ruin other's work, we need unchangable VIntConst class
700: MXnode::MXnode(const char* aname, VStateless_class *abase):
701: Methoded(aname?aname:"xnode", abase)
1.44 paf 702: {
1.6 parser 703: /// DOM1 node
704:
705: // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException);
706: add_native_method("insertBefore", Method::CT_DYNAMIC, _insertBefore, 2, 2);
707: // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException);
708: add_native_method("replaceChild", Method::CT_DYNAMIC, _replaceChild, 2, 2);
709: // Node removeChild(in Node oldChild) raises(DOMException);
710: add_native_method("removeChild", Method::CT_DYNAMIC, _removeChild, 1, 1);
711: // Node appendChild(in Node newChild) raises(DOMException);
712: add_native_method("appendChild", Method::CT_DYNAMIC, _appendChild, 1, 1);
713: // boolean hasChildNodes();
714: add_native_method("hasChildNodes", Method::CT_DYNAMIC, _hasChildNodes, 0, 0);
715: // Node cloneNode(in boolean deep);
716: add_native_method("cloneNode", Method::CT_DYNAMIC, _cloneNode, 1, 1);
717:
718: /// DOM1 element
719:
720: // DOMString getAttribute(in DOMString name);
721: add_native_method("getAttribute", Method::CT_DYNAMIC, _getAttribute, 1, 1);
722: // void setAttribute(in DOMString name, in DOMString value) raises(DOMException);
723: add_native_method("setAttribute", Method::CT_DYNAMIC, _setAttribute, 2, 2);
724: // void removeAttribute(in DOMString name) raises(DOMException);
725: add_native_method("removeAttribute", Method::CT_DYNAMIC, _removeAttribute, 1, 1);
726: // Attr getAttributeNode(in DOMString name);
727: add_native_method("getAttributeNode", Method::CT_DYNAMIC, _getAttributeNode, 1, 1);
728: // Attr setAttributeNode(in Attr newAttr) raises(DOMException);
729: add_native_method("setAttributeNode", Method::CT_DYNAMIC, _setAttributeNode, 1, 1);
730: // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException);
731: add_native_method("removeAttributeNode", Method::CT_DYNAMIC, _removeAttributeNode, 1, 1);
732: // NodeList getElementsByTagName(in DOMString name);
733: add_native_method("getElementsByTagName", Method::CT_DYNAMIC, _getElementsByTagName, 1, 1);
1.39 paf 734: // NodeList getElementsByTagNameNS(in DOMString namespaceURI, in DOMString localName);
735: add_native_method("getElementsByTagNameNS", Method::CT_DYNAMIC, _getElementsByTagNameNS, 2, 2);
1.6 parser 736: // void normalize();
737: add_native_method("normalize", Method::CT_DYNAMIC, _normalize, 0, 0);
1.57 paf 738:
739: /// DOM2 element
740:
1.58 paf 741: // DOMString getAttributeNS(in DOMString namespaceURI, in DOMString localName);
1.57 paf 742: add_native_method("getAttributeNS", Method::CT_DYNAMIC, _getAttributeNS, 2, 2);
1.58 paf 743: // void setAttributeNS(in DOMString namespaceURI, in DOMString qualifiedName, in DOMString value) raises(DOMException);
1.57 paf 744: add_native_method("setAttributeNS", Method::CT_DYNAMIC, _setAttributeNS, 3, 3);
1.58 paf 745: // void removeAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException);
1.57 paf 746: add_native_method("removeAttributeNS", Method::CT_DYNAMIC, _removeAttributeNS, 2, 2);
1.58 paf 747: // Attr getAttributeNodeNS(in DOMString namespaceURI, in DOMString localName);
1.57 paf 748: add_native_method("getAttributeNodeNS", Method::CT_DYNAMIC, _getAttributeNodeNS, 2, 2);
749: // Attr setAttributeNodeNS(in Attr newAttr) raises(DOMException);
750: add_native_method("setAttributeNodeNS", Method::CT_DYNAMIC, _setAttributeNodeNS, 1, 1);
1.58 paf 751: // boolean hasAttribute(in DOMString name) raises(DOMException);
1.57 paf 752: add_native_method("hasAttribute", Method::CT_DYNAMIC, _hasAttribute, 1, 1);
1.58 paf 753: // boolean hasAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException);
1.57 paf 754: add_native_method("hasAttributeNS", Method::CT_DYNAMIC, _hasAttributeNS, 2, 2);
1.6 parser 755:
756: /// parser
1.1 parser 757: // ^node.select[/some/xpath/query] = hash $.#[dnode]
1.66 ! paf 758: add_native_method("select", Method::CT_DYNAMIC, _select, 1, 2);
1.1 parser 759:
1.26 paf 760: // ^node.selectSingle[/some/xpath/query] = first node [if any]
1.66 ! paf 761: add_native_method("selectSingle", Method::CT_DYNAMIC, _selectSingle, 1, 2);
1.26 paf 762: // ^node.selectBool[/some/xpath/query] = bool value [if any]
1.66 ! paf 763: add_native_method("selectBool", Method::CT_DYNAMIC, _selectBool, 1, 2);
1.26 paf 764: // ^node.selectNumber[/some/xpath/query] = double value [if any]
1.66 ! paf 765: add_native_method("selectNumber", Method::CT_DYNAMIC, _selectNumber, 1, 2);
1.26 paf 766: // ^node.selectString[/some/xpath/query] = strinv value [if any]
1.66 ! paf 767: add_native_method("selectString", Method::CT_DYNAMIC, _selectString, 1, 2);
1.20 paf 768:
1.2 parser 769: // consts
770:
1.19 paf 771: #define CONST(name) \
1.59 paf 772: consts.put(String::Body(#name), new VInt(GDOME_##name))
1.2 parser 773:
1.19 paf 774: CONST(ELEMENT_NODE);
1.56 paf 775: CONST(ATTRIBUTE_NODE);
776: CONST(TEXT_NODE);
777: CONST(CDATA_SECTION_NODE);
778: CONST(ENTITY_REFERENCE_NODE);
779: CONST(ENTITY_NODE);
780: CONST(PROCESSING_INSTRUCTION_NODE);
781: CONST(COMMENT_NODE);
782: CONST(DOCUMENT_NODE);
783: CONST(DOCUMENT_TYPE_NODE);
784: CONST(DOCUMENT_FRAGMENT_NODE);
785: CONST(NOTATION_NODE);
786: }
1.1 parser 787:
1.56 paf 788: #else
1.3 parser 789:
1.1 parser 790: // global variable
791:
1.56 paf 792: DECLARE_CLASS_VAR(xnode, 0, 0); // fictive
1.1 parser 793:
794: #endif
E-mail: