Annotation of parser3/src/classes/xnode.C, revision 1.74
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.74 ! paf 10: static const char * const IDENT_XNODE_C="$Date: 2005/12/16 15:08:46 $";
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.72 paf 99: xmlNode& as_node(MethodParams& params, int index, const char* msg) {
1.56 paf 100: Value& value=params.as_no_junction(index, msg);
101: if(Value* vxnode=value.as(VXNODE_TYPE, false))
1.72 paf 102: return static_cast<VXnode*>(vxnode)->get_xmlnode();
103: else
1.41 paf 104: throw Exception("parser.runtime",
1.56 paf 105: 0,
1.6 parser 106: msg);
1.72 paf 107: }
1.56 paf 108:
1.72 paf 109: xmlChar* as_xmlchar(Request& r, MethodParams& params, int index, const char* msg) {
110: return r.transcode(params.as_string(index, msg));
1.6 parser 111: }
112:
1.72 paf 113: xmlAttr& as_attr(MethodParams& params, int index, const char* msg) {
114: xmlNode& xmlnode=as_node(params, index, msg);
115: if(xmlnode.type!=XML_ATTRIBUTE_NODE)
1.41 paf 116: throw Exception("parser.runtime",
1.56 paf 117: 0,
1.6 parser 118: msg);
119:
1.72 paf 120: return *(xmlAttr*)&xmlnode;
121: }
122:
123: static void writeNode(Request& r, VXdoc& xdoc, xmlNode* node) {
1.73 paf 124: if(!node|| xmlHaveGenericErrors())
1.72 paf 125: throw XmlException(0); // OOM, bad name, things like that
126:
127: // write out result
128: r.write_no_lang(xdoc.wrap(*node));
129: }
130:
131: static xmlNode* pa_getAttributeNodeNS(xmlNode& selfNode,
132: const xmlChar* localName,
133: const xmlChar* namespaceURI)
134: {
135: for(xmlNode* currentNode=(xmlNode*)selfNode.properties;
136: currentNode;
137: currentNode=currentNode->next)
138: {
139: if(!namespaceURI || currentNode->ns && xmlStrEqual(currentNode->ns->href, namespaceURI))
140: if(!localName || xmlStrEqual(currentNode->name, localName))
141: return currentNode;
142: }
143: return 0;
144: }
145:
146: xmlNs& pa_xmlMapNs(xmlDoc& doc, const xmlChar *href, const xmlChar *prefix) {
147: assert(href);
148: // prefix can be null
149:
150: xmlNs *cur=doc.oldNs;
151: while (cur != NULL &&
152: ((cur->prefix == NULL && prefix != NULL) ||
153: (cur->prefix != NULL && prefix == NULL) ||
154: !xmlStrEqual (cur->prefix, prefix)) &&
155: !xmlStrEqual (cur->href, href))
156: cur = cur->next;
157:
158: if (cur == NULL) {
159: cur = xmlNewNs (NULL, href, prefix);
160: if(!cur || xmlHaveGenericErrors())
161: throw XmlException(0);
162: cur->next = doc.oldNs;
163: doc.oldNs = cur;
164: }
165:
166: return *cur;
167: }
168:
169: /// todo: проверить, обновляется ли parent!
170: static void pa_addAttributeNode(xmlNode& selfNode, xmlAttr& attrNode)
171: {
172: if(attrNode.type!=XML_ATTRIBUTE_NODE)
1.74 ! paf 173: throw Exception("parser.runtime",
1.72 paf 174: 0,
175: "must be ATTRIBUTE_NODE");
176:
177: /*
178: * Add it at the end to preserve parsing order ...
179: */
180: if (selfNode.properties == NULL) {
181: selfNode.properties = &attrNode;
182: } else {
183: xmlAttrPtr prev = selfNode.properties;
184:
185: while (prev->next != NULL)
186: prev = prev->next;
187: prev->next = &attrNode;
188: attrNode.prev = prev;
189: }
190:
191: if (xmlIsID(selfNode.doc, &selfNode, &attrNode) == 1)
192: xmlAddID(NULL, selfNode.doc, xmlNodeGetContent((xmlNode*)&attrNode), &attrNode);
193: }
194:
195: static const xmlChar *
196: pa_xmlGetNsURI(xmlNode *node) {
197: if (node == NULL || node->ns == NULL)
198: return NULL;
199:
200: return node->ns->href;
201: }
202:
203: #ifndef DOXYGEN
204: struct AccumulateFoundInfo
205: {
206: HashStringValue* hash;
207: VXdoc* vdoc;
208: int index;
209: };
210: #endif
211: static void AccumulateFound(xmlNode& node, AccumulateFoundInfo* info)
212: {
213: info->hash->put(
214: String::Body::Format(info->index++),
215: &info->vdoc->wrap(node));
216: }
217: template<typename I> static void
218: pa_xmlNamedPreorderTraversal (
219: xmlNode *root,
220: xmlChar *tagURI,
221: xmlChar *tagName,
222: void callback(xmlNode& node, I info),
223: I info)
224: {
225: for(xmlNode *iter=root->children; iter; iter = iter->next) {
226: if(iter->type == XML_ELEMENT_NODE &&
227: (xmlStrEqual(iter->name, tagName) ||
228: xmlStrEqual(tagName, (const xmlChar*)"*"))) {
229: if(tagURI != NULL &&
230: (xmlStrEqual(pa_xmlGetNsURI(iter), tagURI) ||
231: xmlStrEqual(tagURI, (const xmlChar*)"*")))
232: callback(*iter, info);
233: else if(tagURI == NULL)
234: callback(*iter, info);
235: }
236: pa_xmlNamedPreorderTraversal(iter, tagURI, tagName, callback, info);
237: }
238:
239: return;
1.6 parser 240: }
1.1 parser 241:
1.72 paf 242:
1.1 parser 243: // methods
244:
1.6 parser 245: // DOM1 node
246:
247: // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException);
1.56 paf 248: static void _insertBefore(Request& r, MethodParams& params) {
249: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 250: VXdoc& vxdoc=vnode.get_vxdoc();
251:
252: //xmlNode& selfNode=vnode.get_xmlnode();
253: xmlNode& newChild=as_node(params, 0, "newChild must be node");
254: xmlNode& refChild=as_node(params, 1, "refChild must be node");
1.6 parser 255:
1.72 paf 256: xmlNode* retNode=xmlAddPrevSibling(&refChild, &newChild);
257: // write out result
258: writeNode(r, vxdoc, retNode);
1.6 parser 259: }
260:
261: // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException);
1.56 paf 262: static void _replaceChild(Request& r, MethodParams& params) {
263: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 264: VXdoc& vxdoc=vnode.get_vxdoc();
265: xmlDoc& xmldoc=vxdoc.get_xmldoc();
266: xmlNode& selfNode=vnode.get_xmlnode();
267: xmlNode& newChild=as_node(params, 0, "newChild must be node");
1.74 ! paf 268: xmlNode& oldChild=as_node(params, 1, "oldChild must be node");
1.72 paf 269:
270: if(newChild.doc!=&xmldoc)
1.74 ! paf 271: throw Exception("xml.dom",
1.72 paf 272: 0,
273: "WRONG_DOCUMENT_ERR");
274: if(oldChild.doc!=&xmldoc)
1.74 ! paf 275: throw Exception("xml.dom",
1.72 paf 276: 0,
277: "WRONG_DOCUMENT_ERR");
278:
1.74 ! paf 279: if(oldChild.parent!=&selfNode)
! 280: throw Exception("xml.dom",
! 281: 0,
! 282: "NOT_FOUND_ERR");
! 283:
1.72 paf 284: xmlNode* refChild=oldChild.next;
285: xmlUnlinkNode(&oldChild);
286: xmlNode* retNode;
287: if(refChild)
288: retNode=xmlAddPrevSibling(refChild, &newChild);
289: else
290: retNode=xmlAddChild(&selfNode, &newChild);
291:
292: // write out result
293: writeNode(r, vxdoc, retNode);
1.6 parser 294: }
295:
296: // Node removeChild(in Node oldChild) raises(DOMException);
1.56 paf 297: static void _removeChild(Request& r, MethodParams& params) {
298: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 299: VXdoc& vxdoc=vnode.get_vxdoc();
300: xmlDoc& xmldoc=vxdoc.get_xmldoc();
301: // xmlNode& selfNode=vnode.get_xmlnode();
302: xmlNode& oldChild=as_node(params, 0, "refChild must be node");
1.6 parser 303:
1.72 paf 304: if(oldChild.doc!=&xmldoc)
1.74 ! paf 305: throw Exception("xml.dom",
1.72 paf 306: 0,
307: "WRONG_DOCUMENT_ERR");
308:
309: xmlUnlinkNode(&oldChild);
310: // write out result
311: writeNode(r, vxdoc, &oldChild);
1.6 parser 312: }
313:
314: // Node appendChild(in Node newChild) raises(DOMException);
1.56 paf 315: static void _appendChild(Request& r, MethodParams& params) {
316: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 317: VXdoc& vxdoc=vnode.get_vxdoc();
318: xmlNode& selfNode=vnode.get_xmlnode();
319: xmlNode& newChild=as_node(params, 0, "newChild must be node");
1.6 parser 320:
1.72 paf 321: xmlNode* retNode=xmlAddChild(&selfNode, &newChild);
322: // write out result
323: writeNode(r, vxdoc, retNode);
1.6 parser 324: }
325:
326: // boolean hasChildNodes();
1.56 paf 327: static void _hasChildNodes(Request& r, MethodParams&) {
328: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 329: xmlNode& node=vnode.get_xmlnode();
1.6 parser 330:
331: // write out result
1.72 paf 332: bool result=node.children!=0;
1.56 paf 333: r.write_no_lang(*new VBool(result));
1.6 parser 334: }
335:
336: // Node cloneNode(in boolean deep);
1.56 paf 337: static void _cloneNode(Request& r, MethodParams& params) {
338: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 339: xmlNode& selfNode=vnode.get_xmlnode();
340: VXdoc& vxdoc=vnode.get_vxdoc();
341: xmlDoc& xmldoc=vxdoc.get_xmldoc();
1.6 parser 342:
1.56 paf 343: bool deep=params.as_bool(0, "deep must be bool", r);
1.6 parser 344:
1.72 paf 345: xmlNode* retNode=xmlDocCopyNode(&selfNode, &xmldoc, deep?1: 0);
1.6 parser 346: // write out result
1.72 paf 347: writeNode(r, vxdoc, retNode);
1.6 parser 348: }
349:
350: // DOM1 element
351:
1.72 paf 352: xmlNode& get_self_element(VXnode& vnode) {
353: xmlNode& node=vnode.get_xmlnode();
1.6 parser 354:
1.72 paf 355: if(node.type!=XML_ELEMENT_NODE)
1.41 paf 356: throw Exception("parser.runtime",
1.56 paf 357: 0,
1.51 paf 358: "method can only be called on nodes of ELEMENT type");
1.6 parser 359:
1.72 paf 360: return node;
1.6 parser 361: }
362:
1.56 paf 363:
364: static void _getAttribute(Request& r, MethodParams& params) {
1.67 paf 365: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 366: xmlNode& element=get_self_element(vnode);
367: const xmlChar* name=as_xmlchar(r, params, 0, "name must be string");
1.6 parser 368:
1.72 paf 369: // todo: when name="xmlns"
370: xmlChar* attribute_value=xmlGetProp(&element, name);
1.6 parser 371: // write out result
1.68 paf 372: r.write_pass_lang(r.transcode(attribute_value));
1.6 parser 373: }
374:
375: // void setAttribute(in DOMString name, in DOMString value) raises(DOMException);
1.56 paf 376: static void _setAttribute(Request& r, MethodParams& params) {
1.67 paf 377: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 378: xmlNode& element=get_self_element(vnode);
379: const xmlChar* name=as_xmlchar(r, params, 0, "name must be string");
380: const xmlChar* attribute_value=as_xmlchar(r, params, 1, "value must be string");
381:
382: // todo: when name="xmlns"
383: if(!xmlSetProp(&element, name, attribute_value))
384: throw XmlException(0);
1.6 parser 385: }
386:
387: // void removeAttribute(in DOMString name) raises(DOMException);
1.56 paf 388: static void _removeAttribute(Request& r, MethodParams& params) {
1.67 paf 389: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 390: xmlNode& element=get_self_element(vnode);
391: const xmlChar* name=as_xmlchar(r, params, 0, "name must be string");
1.6 parser 392:
1.72 paf 393: // todo: when name="xmlns"
394: xmlUnsetProp(&element, name);
1.6 parser 395: }
396:
397: // Attr getAttributeNode(in DOMString name);
1.56 paf 398: static void _getAttributeNode(Request& r, MethodParams& params) {
1.67 paf 399: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 400: VXdoc& vxdoc=vnode.get_vxdoc();
401: xmlNode& element=get_self_element(vnode);
402: const xmlChar* localName=as_xmlchar(r, params, 0, "name must be string");
1.6 parser 403:
1.72 paf 404: if(xmlNode* retNode=pa_getAttributeNodeNS(element, localName, 0)){
1.6 parser 405: // write out result
1.72 paf 406: writeNode(r, vxdoc, retNode);
407: }
1.6 parser 408: }
409:
410: // Attr setAttributeNode(in Attr newAttr) raises(DOMException);
1.72 paf 411: // Attr setAttributeNodeNS(in Attr newAttr) raises(DOMException);
1.56 paf 412: static void _setAttributeNode(Request& r, MethodParams& params) {
1.67 paf 413: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 414: VXdoc& vxdoc=vnode.get_vxdoc();
415: xmlNode& element=get_self_element(vnode);
416: xmlDoc& xmldoc=vxdoc.get_xmldoc();
417: xmlAttr& newAttr=as_attr(params, 0, "newAttr must be ATTRIBUTE node");
418:
419: if(newAttr.doc!=&xmldoc)
1.74 ! paf 420: throw Exception("xml.dom",
1.72 paf 421: 0,
422: "WRONG_DOCUMENT_ERR");
1.6 parser 423:
1.72 paf 424: if(newAttr.parent)
1.74 ! paf 425: throw Exception("xml.dom",
1.72 paf 426: 0,
427: "INUSE_ATTRIBUTE_ERR");
428:
429: if(xmlNode* retNode=pa_getAttributeNodeNS(element, newAttr.name, pa_xmlGetNsURI((xmlNode*)&newAttr))) {
1.19 paf 430: // write out result
1.72 paf 431: writeNode(r, vxdoc, retNode);
432: xmlUnlinkNode(retNode);
433: }
434:
435: pa_addAttributeNode(element, newAttr);
1.6 parser 436: }
437:
438: // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException);
1.56 paf 439: static void _removeAttributeNode(Request& r, MethodParams& params) {
1.67 paf 440: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 441: VXdoc& vxdoc=vnode.get_vxdoc();
442: xmlNode& element=get_self_element(vnode);
443: xmlAttr& oldAttr=as_attr(params, 0, "oldAttr must be ATTRIBUTE node");
444:
445: if(oldAttr.parent!=&element)
1.74 ! paf 446: throw Exception("xml.dom",
1.72 paf 447: 0,
448: "NOT_FOUND_ERR");
1.6 parser 449:
1.72 paf 450: xmlUnlinkNode((xmlNode*)&oldAttr);
451:
452: // write out result
453: writeNode(r, vxdoc, (xmlNode*)&oldAttr);
1.6 parser 454: }
455:
456: // NodeList getElementsByTagName(in DOMString name);
1.56 paf 457: static void _getElementsByTagName(Request& r, MethodParams& params) {
1.67 paf 458: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 459: VXdoc& vxdoc=vnode.get_vxdoc();
460: xmlNode& xmlnode=vnode.get_xmlnode();
1.6 parser 461:
1.72 paf 462: xmlChar* tagName=as_xmlchar(r, params, 0, "name must be string");
1.6 parser 463:
1.56 paf 464: VHash& result=*new VHash;
1.72 paf 465: AccumulateFoundInfo info={&result.hash(), &vxdoc, 0};
466: pa_xmlNamedPreorderTraversal(&xmlnode,
467: 0,
468: tagName,
469: AccumulateFound,
470: &info);
1.6 parser 471:
472: // write out result
473: r.write_no_lang(result);
474: }
475:
1.57 paf 476: // DOM 2
477:
1.58 paf 478: // DOMString getAttributeNS(in DOMString namespaceURI, in DOMString localName);
1.57 paf 479: static void _getAttributeNS(Request& r, MethodParams& params) {
1.67 paf 480: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 481: xmlNode& element=get_self_element(vnode);
1.57 paf 482:
1.72 paf 483: xmlChar* namespaceURI=as_xmlchar(r, params, 0, "namespaceURI must be string");
484: xmlChar* localName=as_xmlchar(r, params, 1, "localName must be string");
1.57 paf 485:
1.72 paf 486: // todo: when name="xmlns"
487: xmlChar* attribute_value=xmlGetNsProp(&element, localName, namespaceURI);
1.57 paf 488: // write out result
1.68 paf 489: r.write_pass_lang(r.transcode(attribute_value));
1.57 paf 490: }
491:
1.72 paf 492:
1.58 paf 493: // void setAttributeNS(in DOMString namespaceURI, in DOMString qualifiedName, in DOMString value) raises(DOMException);
1.57 paf 494: static void _setAttributeNS(Request& r, MethodParams& params) {
1.67 paf 495: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 496: xmlNode& element=get_self_element(vnode);
497: VXdoc& vxdoc=vnode.get_vxdoc();
498: xmlDoc& xmldoc=vxdoc.get_xmldoc();
499: const xmlChar* namespaceURI=as_xmlchar(r, params, 0, "namespaceURI must be string");
500: const xmlChar* qualifiedName=as_xmlchar(r, params, 1, "qualifiedName must be string");
501: const xmlChar* attribute_value=as_xmlchar(r, params, 2, "value must be string");
502:
503: xmlChar* prefix=0;
504: xmlChar* localName=xmlSplitQName2(qualifiedName, &prefix);
505:
506: // todo: name=xmlns
507: xmlAttr* attrNode;
508: if(localName) {
509: xmlNs& ns=pa_xmlMapNs(xmldoc, namespaceURI, prefix);
510:
511: attrNode=xmlSetNsProp(&element, &ns,
512: localName,
513: attribute_value);
514: } else {
515: attrNode=xmlSetProp(&element,
516: qualifiedName/*unqualified, actually*/,
517: attribute_value);
518: }
519:
520: if(!attrNode)
521: throw XmlException(0);
1.57 paf 522: }
523:
1.58 paf 524: // void removeAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException);
1.57 paf 525: static void _removeAttributeNS(Request& r, MethodParams& params) {
1.67 paf 526: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 527: xmlNode& element=get_self_element(vnode);
528: VXdoc& vxdoc=vnode.get_vxdoc();
529: xmlDoc& xmldoc=vxdoc.get_xmldoc();
530: const xmlChar* namespaceURI=as_xmlchar(r, params, 0, "namespaceURI must be string");
531: const xmlChar* localName=as_xmlchar(r, params, 1, "localName must be string");
532:
533: // todo: when name="xmlns"
534: xmlNs& ns=pa_xmlMapNs(xmldoc, namespaceURI, 0);
535: xmlUnsetNsProp(&element, &ns, localName);
1.57 paf 536: }
537:
1.58 paf 538: // Attr getAttributeNodeNS(in DOMString namespaceURI, in DOMString localName);
1.57 paf 539: static void _getAttributeNodeNS(Request& r, MethodParams& params) {
1.67 paf 540: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 541: VXdoc& vxdoc=vnode.get_vxdoc();
542: xmlNode& element=get_self_element(vnode);
543: const xmlChar* namespaceURI=as_xmlchar(r, params, 0, "namespaceURI must be string");
544: const xmlChar* localName=as_xmlchar(r, params, 1, "localName must be string");
1.57 paf 545:
1.72 paf 546: if(xmlNode* retNode=pa_getAttributeNodeNS(element, localName, namespaceURI)){
1.57 paf 547: // write out result
1.72 paf 548: writeNode(r, vxdoc, retNode);
549: }
550: }
1.57 paf 551:
1.58 paf 552: // boolean hasAttribute(in DOMString name) raises(DOMException);
1.57 paf 553: static void _hasAttribute(Request& r, MethodParams& params) {
1.67 paf 554: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 555: xmlNode& element=get_self_element(vnode);
1.57 paf 556:
1.72 paf 557: const xmlChar* name=as_xmlchar(r, params, 0, "name must be string");
1.57 paf 558:
1.72 paf 559: xmlChar* prop=xmlGetProp(&element, name);
560: // todo: when name="xmlns"
1.57 paf 561: // write out result
1.72 paf 562: r.write_no_lang(*new VBool(prop!=0));
1.57 paf 563: }
564:
1.58 paf 565: // boolean hasAttributeNS(n DOMString namespaceURI, in DOMString localName) raises(DOMException);
1.57 paf 566: static void _hasAttributeNS(Request& r, MethodParams& params) {
1.67 paf 567: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 568: xmlNode& element=get_self_element(vnode);
1.57 paf 569:
1.72 paf 570: const xmlChar* namespaceURI=as_xmlchar(r, params, 0, "namespaceURI must be string");
571: const xmlChar* localName=as_xmlchar(r, params, 1, "localName must be string");
1.57 paf 572:
1.72 paf 573: xmlChar* prop=xmlGetNsProp(&element, localName, namespaceURI);
1.57 paf 574: // write out result
1.72 paf 575: r.write_no_lang(*new VBool(prop!=0));
1.57 paf 576: }
577:
1.56 paf 578: static void _getElementsByTagNameNS(Request& r, MethodParams& params) {
1.67 paf 579: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 580: VXdoc& vdoc=vnode.get_vxdoc();
581: xmlDoc& xmldoc=vdoc.get_xmldoc();
1.39 paf 582:
583: // namespaceURI;localName
1.72 paf 584: xmlChar* namespaceURI=as_xmlchar(r, params, 0, "namespaceURI must be string");
585: xmlChar* localName=as_xmlchar(r, params, 1, "name must be string");
1.39 paf 586:
1.56 paf 587: VHash& result=*new VHash;
1.72 paf 588: AccumulateFoundInfo info={&result.hash(), &vdoc, 0};
589: pa_xmlNamedPreorderTraversal((xmlNode*)&xmldoc,
590: namespaceURI,
591: localName,
592: AccumulateFound,
593: &info);
1.39 paf 594:
595: // write out result
596: r.write_no_lang(result);
597: }
598:
1.72 paf 599:
1.6 parser 600: // void normalize();
1.72 paf 601: static void _normalize(Request&, MethodParams&) {
602: /*maybe someday
1.56 paf 603: VXnode& vnode=GET_SELF(r, VXnode);
1.72 paf 604: xmlNode& selfNode=vnode.get_xmlnode();
1.6 parser 605:
1.19 paf 606: gdome_n_normalize(selfNode, &exc);
607: if(exc)
1.60 paf 608: throw XmlException(0, exc);
1.72 paf 609: */
1.6 parser 610: }
1.25 paf 611:
1.66 paf 612: #ifndef DOXYGEN
613: struct Register_one_ns_info {
614: Request* r;
615: xmlXPathContextPtr ctxt;
616: };
617: #endif
618: static void register_one_ns(
619: HashStringValue::key_type key,
620: HashStringValue::value_type value,
621: Register_one_ns_info* info) {
622: if(const String* svalue=value->get_string())
623: xmlXPathRegisterNs(info->ctxt,
1.72 paf 624: info->r->transcode(key),
625: info->r->transcode(*svalue));
1.66 paf 626: else
627: throw Exception("parser.runtime",
628: new String(key, String::L_TAINTED),
629: "value is %s, must be string or number", value->type());
630: }
1.56 paf 631: static void _selectX(Request& r, MethodParams& params,
632: void (*handler)(Request& r,
1.26 paf 633: const String& expression,
634: xmlXPathObject_auto_ptr res,
1.67 paf 635: VXdoc& xdoc,
1.72 paf 636: Value*& result))
637: {
1.56 paf 638: VXnode& vnode=GET_SELF(r, VXnode);
1.74 ! paf 639: xmlNode& xmlnode=vnode.get_xmlnode();
1.72 paf 640: VXdoc& vdoc=vnode.get_vxdoc();
641: xmlDoc& xmldoc=vdoc.get_xmldoc();
1.1 parser 642:
643: // expression
1.56 paf 644: const String& expression=params.as_string(0, "expression must be string");
1.72 paf 645: xmlXPathContext_auto_ptr ctxt(xmlXPathNewContext(&xmldoc));
1.67 paf 646: {
1.66 paf 647: Register_one_ns_info info={&r, ctxt.get()};
1.72 paf 648: vdoc.search_namespaces.hash().for_each(register_one_ns, &info);
1.66 paf 649: }
1.74 ! paf 650: ctxt->node=&xmlnode;
1.25 paf 651: /*error to stderr for now*/
652: xmlXPathObject_auto_ptr res(
1.72 paf 653: xmlXPathEvalExpression(r.transcode(expression), ctxt.get()));
1.28 paf 654:
1.72 paf 655: if(xmlHaveGenericErrors())
656: throw XmlException(0);
1.25 paf 657:
1.56 paf 658: Value* result=0;
1.25 paf 659: if(res.get())
1.72 paf 660: handler(r, expression, res, vdoc, result);
1.44 paf 661: if(result)
1.26 paf 662: r.write_no_lang(*result);
663: }
1.25 paf 664:
1.72 paf 665: static void selectNodesHandler(Request&,
1.56 paf 666: const String& expression,
667: xmlXPathObject_auto_ptr res,
1.67 paf 668: VXdoc& xdoc,
1.56 paf 669: Value*& result) {
670: VHash& vhash=*new VHash; result=&vhash;
1.26 paf 671: switch(res->type) {
672: case XPATH_UNDEFINED:
673: break;
674: case XPATH_NODESET:
1.40 paf 675: if(res->nodesetval)
676: if(int size=res->nodesetval->nodeNr) {
1.56 paf 677: HashStringValue& hash=vhash.hash();
678: for(int i=0; i<size; i++)
679: hash.put(
1.59 paf 680: String::Body::Format(i),
1.72 paf 681: &xdoc.wrap(*res->nodesetval->nodeTab[i]));
1.1 parser 682: }
1.26 paf 683: break;
684: default:
1.74 ! paf 685: throw Exception("parser.runtime",
1.26 paf 686: &expression,
687: "wrong xmlXPathEvalExpression result type (%d)", res->type);
688: break; // never
689: }
690: }
691:
1.56 paf 692: static void selectNodeHandler(Request& r,
693: const String& expression,
1.67 paf 694: xmlXPathObject_auto_ptr res,
695: VXdoc& xdoc,
696: Value*& result) {
1.26 paf 697: switch(res->type) {
698: case XPATH_UNDEFINED:
699: break;
700: case XPATH_NODESET:
1.40 paf 701: if(res->nodesetval && res->nodesetval->nodeNr) { // empty result strangly has NODESET res->type
1.26 paf 702: if(res->nodesetval->nodeNr>1)
1.41 paf 703: throw Exception("parser.runtime",
1.56 paf 704: &expression,
705: "resulted not in a single node (%d)", res->nodesetval->nodeNr);
1.26 paf 706:
1.72 paf 707: result=&xdoc.wrap(*res->nodesetval->nodeTab[0]);
1.25 paf 708: }
1.26 paf 709: break;
710: case XPATH_BOOLEAN:
1.56 paf 711: result=new VBool(res->boolval!=0);
1.26 paf 712: break;
713: case XPATH_NUMBER:
1.56 paf 714: result=new VDouble(res->floatval);
1.26 paf 715: break;
716: case XPATH_STRING:
1.56 paf 717: result=new VString(r.transcode((xmlChar*)res->stringval));
1.26 paf 718: break;
719: default:
1.41 paf 720: throw Exception("parser.runtime",
1.26 paf 721: &expression,
722: "wrong xmlXPathEvalExpression result type (%d)", res->type);
723: }
724: }
725:
1.62 paf 726: static void selectBoolHandler(Request&,
1.56 paf 727: const String& expression,
728: xmlXPathObject_auto_ptr res,
1.67 paf 729: VXdoc& /*xdoc*/,
1.56 paf 730: Value*& result) {
1.26 paf 731: switch(res->type) {
732: case XPATH_BOOLEAN:
1.56 paf 733: result=new VBool(res->boolval!=0);
1.26 paf 734: break;
735: case XPATH_NODESET:
1.40 paf 736: if(!(res->nodesetval && res->nodesetval->nodeNr))
1.26 paf 737: break;
738: // else[nodeset] fall down to default
739: default:
1.41 paf 740: throw Exception("parser.runtime",
1.26 paf 741: &expression,
742: "wrong xmlXPathEvalExpression result type (%d)", res->type);
743: break; // never
744: }
745: }
1.1 parser 746:
1.62 paf 747: static void selectNumberHandler(Request&,
1.56 paf 748: const String& expression,
749: xmlXPathObject_auto_ptr res,
1.67 paf 750: VXdoc& /*xdoc*/,
1.56 paf 751: Value*& result) {
1.26 paf 752: switch(res->type) {
753: case XPATH_NUMBER:
1.56 paf 754: result=new VDouble(res->floatval);
1.26 paf 755: break;
756: case XPATH_NODESET:
1.40 paf 757: if(!(res->nodesetval && res->nodesetval->nodeNr))
1.26 paf 758: break;
759: // else[nodeset] fall down to default
760: default:
1.41 paf 761: throw Exception("parser.runtime",
1.26 paf 762: &expression,
763: "wrong xmlXPathEvalExpression result type (%d)", res->type);
764: break; // never
765: }
766: }
767:
1.56 paf 768: static void selectStringHandler(Request& r,
1.26 paf 769: const String& expression,
770: xmlXPathObject_auto_ptr res,
1.67 paf 771: VXdoc& /*xdoc*/,
1.56 paf 772: Value*& result) {
1.26 paf 773: switch(res->type) {
774: case XPATH_UNDEFINED:
775: break;
776: case XPATH_STRING:
1.56 paf 777: result=new VString(r.transcode((xmlChar*)res->stringval));
1.26 paf 778: break;
779: case XPATH_NODESET:
1.40 paf 780: if(!(res->nodesetval && res->nodesetval->nodeNr))
1.26 paf 781: break;
782: // else[nodeset] fall down to default
783: default:
1.41 paf 784: throw Exception("parser.runtime",
1.26 paf 785: &expression,
786: "wrong xmlXPathEvalExpression result type (%d)", res->type);
787: break; // never
1.1 parser 788: }
789: }
1.25 paf 790:
1.56 paf 791: static void _select(Request& r, MethodParams& params) {
792: _selectX(r, params,
1.26 paf 793: selectNodesHandler);
794: }
795:
1.56 paf 796: static void _selectSingle(Request& r, MethodParams& params) {
797: _selectX(r, params,
1.26 paf 798: selectNodeHandler);
799: }
1.1 parser 800:
1.56 paf 801: static void _selectBool(Request& r, MethodParams& params) {
802: _selectX(r, params,
1.26 paf 803: selectBoolHandler);
804: }
1.20 paf 805:
1.56 paf 806: static void _selectNumber(Request& r, MethodParams& params) {
807: _selectX(r, params,
1.26 paf 808: selectNumberHandler);
809: }
1.24 paf 810:
1.56 paf 811: static void _selectString(Request& r, MethodParams& params) {
812: _selectX(r, params,
1.26 paf 813: selectStringHandler);
1.1 parser 814: }
1.20 paf 815:
1.1 parser 816: // constructor
817:
1.56 paf 818: /// @bug one can change const and ruin other's work, we need unchangable VIntConst class
819: MXnode::MXnode(const char* aname, VStateless_class *abase):
820: Methoded(aname?aname:"xnode", abase)
1.44 paf 821: {
1.6 parser 822: /// DOM1 node
823:
824: // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException);
825: add_native_method("insertBefore", Method::CT_DYNAMIC, _insertBefore, 2, 2);
826: // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException);
827: add_native_method("replaceChild", Method::CT_DYNAMIC, _replaceChild, 2, 2);
828: // Node removeChild(in Node oldChild) raises(DOMException);
829: add_native_method("removeChild", Method::CT_DYNAMIC, _removeChild, 1, 1);
830: // Node appendChild(in Node newChild) raises(DOMException);
831: add_native_method("appendChild", Method::CT_DYNAMIC, _appendChild, 1, 1);
832: // boolean hasChildNodes();
833: add_native_method("hasChildNodes", Method::CT_DYNAMIC, _hasChildNodes, 0, 0);
834: // Node cloneNode(in boolean deep);
835: add_native_method("cloneNode", Method::CT_DYNAMIC, _cloneNode, 1, 1);
836:
837: /// DOM1 element
838:
839: // DOMString getAttribute(in DOMString name);
840: add_native_method("getAttribute", Method::CT_DYNAMIC, _getAttribute, 1, 1);
841: // void setAttribute(in DOMString name, in DOMString value) raises(DOMException);
842: add_native_method("setAttribute", Method::CT_DYNAMIC, _setAttribute, 2, 2);
843: // void removeAttribute(in DOMString name) raises(DOMException);
844: add_native_method("removeAttribute", Method::CT_DYNAMIC, _removeAttribute, 1, 1);
845: // Attr getAttributeNode(in DOMString name);
846: add_native_method("getAttributeNode", Method::CT_DYNAMIC, _getAttributeNode, 1, 1);
847: // Attr setAttributeNode(in Attr newAttr) raises(DOMException);
848: add_native_method("setAttributeNode", Method::CT_DYNAMIC, _setAttributeNode, 1, 1);
849: // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException);
850: add_native_method("removeAttributeNode", Method::CT_DYNAMIC, _removeAttributeNode, 1, 1);
851: // NodeList getElementsByTagName(in DOMString name);
852: add_native_method("getElementsByTagName", Method::CT_DYNAMIC, _getElementsByTagName, 1, 1);
1.39 paf 853: // NodeList getElementsByTagNameNS(in DOMString namespaceURI, in DOMString localName);
854: add_native_method("getElementsByTagNameNS", Method::CT_DYNAMIC, _getElementsByTagNameNS, 2, 2);
1.6 parser 855: // void normalize();
856: add_native_method("normalize", Method::CT_DYNAMIC, _normalize, 0, 0);
1.57 paf 857:
858: /// DOM2 element
859:
1.58 paf 860: // DOMString getAttributeNS(in DOMString namespaceURI, in DOMString localName);
1.57 paf 861: add_native_method("getAttributeNS", Method::CT_DYNAMIC, _getAttributeNS, 2, 2);
1.58 paf 862: // void setAttributeNS(in DOMString namespaceURI, in DOMString qualifiedName, in DOMString value) raises(DOMException);
1.57 paf 863: add_native_method("setAttributeNS", Method::CT_DYNAMIC, _setAttributeNS, 3, 3);
1.58 paf 864: // void removeAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException);
1.57 paf 865: add_native_method("removeAttributeNS", Method::CT_DYNAMIC, _removeAttributeNS, 2, 2);
1.58 paf 866: // Attr getAttributeNodeNS(in DOMString namespaceURI, in DOMString localName);
1.57 paf 867: add_native_method("getAttributeNodeNS", Method::CT_DYNAMIC, _getAttributeNodeNS, 2, 2);
868: // Attr setAttributeNodeNS(in Attr newAttr) raises(DOMException);
1.72 paf 869: add_native_method("setAttributeNodeNS", Method::CT_DYNAMIC, _setAttributeNode, 1, 1);
1.58 paf 870: // boolean hasAttribute(in DOMString name) raises(DOMException);
1.57 paf 871: add_native_method("hasAttribute", Method::CT_DYNAMIC, _hasAttribute, 1, 1);
1.58 paf 872: // boolean hasAttributeNS(in DOMString namespaceURI, in DOMString localName) raises(DOMException);
1.57 paf 873: add_native_method("hasAttributeNS", Method::CT_DYNAMIC, _hasAttributeNS, 2, 2);
1.6 parser 874:
875: /// parser
1.1 parser 876: // ^node.select[/some/xpath/query] = hash $.#[dnode]
1.67 paf 877: add_native_method("select", Method::CT_DYNAMIC, _select, 1, 1);
1.1 parser 878:
1.26 paf 879: // ^node.selectSingle[/some/xpath/query] = first node [if any]
1.67 paf 880: add_native_method("selectSingle", Method::CT_DYNAMIC, _selectSingle, 1, 1);
1.26 paf 881: // ^node.selectBool[/some/xpath/query] = bool value [if any]
1.67 paf 882: add_native_method("selectBool", Method::CT_DYNAMIC, _selectBool, 1, 1);
1.26 paf 883: // ^node.selectNumber[/some/xpath/query] = double value [if any]
1.67 paf 884: add_native_method("selectNumber", Method::CT_DYNAMIC, _selectNumber, 1, 1);
1.26 paf 885: // ^node.selectString[/some/xpath/query] = strinv value [if any]
1.67 paf 886: add_native_method("selectString", Method::CT_DYNAMIC, _selectString, 1, 1);
1.20 paf 887:
1.2 parser 888: // consts
889:
1.19 paf 890: #define CONST(name) \
1.72 paf 891: consts.put(String::Body(#name), new VInt(XML_##name))
892: #define CONST2(name, value) \
893: consts.put(String::Body(#name), new VInt(value))
1.2 parser 894:
1.19 paf 895: CONST(ELEMENT_NODE);
1.56 paf 896: CONST(ATTRIBUTE_NODE);
897: CONST(TEXT_NODE);
898: CONST(CDATA_SECTION_NODE);
1.72 paf 899: CONST2(ENTITY_REFERENCE_NODE, XML_ENTITY_REF_NODE);
1.56 paf 900: CONST(ENTITY_NODE);
1.72 paf 901: CONST2(PROCESSING_INSTRUCTION_NODE, XML_PI_NODE);
1.56 paf 902: CONST(COMMENT_NODE);
903: CONST(DOCUMENT_NODE);
904: CONST(DOCUMENT_TYPE_NODE);
1.72 paf 905: CONST2(DOCUMENT_FRAGMENT_NODE, XML_DOCUMENT_FRAG_NODE);
1.56 paf 906: CONST(NOTATION_NODE);
907: }
1.1 parser 908:
1.56 paf 909: #else
1.3 parser 910:
1.1 parser 911: // global variable
912:
1.56 paf 913: DECLARE_CLASS_VAR(xnode, 0, 0); // fictive
1.1 parser 914:
915: #endif
E-mail: