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