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