Annotation of parser3/src/classes/xnode.C, revision 1.6
1.1 parser 1: /** @file
2: Parser: @b dom parser class.
3:
4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
5: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
6:
1.6 ! parser 7: $Id: xnode.C,v 1.5 2001/10/11 14:58:15 parser Exp $
1.1 parser 8: */
9: #include "classes.h"
10: #ifdef XML
11:
12: #include "pa_request.h"
13: #include "pa_vxnode.h"
14:
15: #include "xnode.h"
16:
17: #include <util/XMLString.hpp>
18: #include <XalanSourceTree/XalanSourceTreeDOMSupport.hpp>
19: #include <XPath/XPathEvaluator.hpp>
20: #include <XPath/NodeRefList.hpp>
1.6 ! parser 21: #include <XalanDOM/XalanElement.hpp>
! 22: #include <XalanDOM/XalanAttr.hpp>
! 23: #include <XalanDOM/XalanNodeList.hpp>
1.1 parser 24:
25: // defines
26:
27: #define XNODE_CLASS_NAME "xnode"
28:
1.6 ! parser 29: // helpers
! 30:
! 31: XalanNode& as_node(Pool& pool, const String& method_name, MethodParams *params,
! 32: int index, const char *msg) {
! 33: Value& value=params->as_no_junction(index, msg);
! 34: if(strcmp(value.type(), VXNODE_TYPE)!=0)
! 35: PTHROW(0, 0,
! 36: &method_name,
! 37: msg);
! 38:
! 39: VXnode& vnode=*static_cast<VXnode *>(&value);
! 40: return vnode.get_node(pool, &method_name);
! 41: }
! 42:
! 43: // helpers
! 44:
! 45: XalanAttr& as_attr(Pool& pool, const String& method_name, MethodParams *params,
! 46: int index, const char *msg) {
! 47: XalanNode& node=as_node(pool, method_name, params, index, msg);
! 48:
! 49: if(node.getNodeType()!=XalanNode::ATTRIBUTE_NODE)
! 50: PTHROW(0, 0,
! 51: &method_name,
! 52: msg);
! 53:
! 54: return *reinterpret_cast<XalanAttr *>(&node);
! 55: }
1.1 parser 56:
57: // methods
58:
1.6 ! parser 59: // DOM1 node
! 60:
! 61: // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException);
! 62: static void _insertBefore(Request& r, const String& method_name, MethodParams *params) {
! 63: Pool& pool=r.pool();
! 64: VXnode& vnode=*static_cast<VXnode *>(r.self);
! 65: XalanNode& node=vnode.get_node(pool, &method_name);
! 66:
! 67: XalanNode& newChild=as_node(pool, method_name, params, 0, "newChild must be node");
! 68: XalanNode& refChild=as_node(pool, method_name, params, 1, "refChild must be node");
! 69:
! 70: try {
! 71: node.insertBefore(&newChild, &refChild);
! 72: } catch(const XalanDOMException& e) {
! 73: pool.exception()._throw(pool, &method_name, e);
! 74: }
! 75: }
! 76:
! 77: // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException);
! 78: static void _replaceChild(Request& r, const String& method_name, MethodParams *params) {
! 79: Pool& pool=r.pool();
! 80: VXnode& vnode=*static_cast<VXnode *>(r.self);
! 81: XalanNode& node=vnode.get_node(pool, &method_name);
! 82:
! 83: XalanNode& newChild=as_node(pool, method_name, params, 0, "newChild must be node");
! 84: XalanNode& refChild=as_node(pool, method_name, params, 1, "refChild must be node");
! 85:
! 86: try {
! 87: node.replaceChild(&newChild, &refChild);
! 88: } catch(const XalanDOMException& e) {
! 89: pool.exception()._throw(pool, &method_name, e);
! 90: }
! 91: }
! 92:
! 93: // Node removeChild(in Node oldChild) raises(DOMException);
! 94: static void _removeChild(Request& r, const String& method_name, MethodParams *params) {
! 95: Pool& pool=r.pool();
! 96: VXnode& vnode=*static_cast<VXnode *>(r.self);
! 97: XalanNode& node=vnode.get_node(pool, &method_name);
! 98:
! 99: XalanNode& oldChild=as_node(pool, method_name, params, 0, "oldChild must be node");
! 100:
! 101: try {
! 102: node.removeChild(&oldChild);
! 103: } catch(const XalanDOMException& e) {
! 104: pool.exception()._throw(pool, &method_name, e);
! 105: }
! 106: }
! 107:
! 108: // Node appendChild(in Node newChild) raises(DOMException);
! 109: static void _appendChild(Request& r, const String& method_name, MethodParams *params) {
! 110: Pool& pool=r.pool();
! 111: VXnode& vnode=*static_cast<VXnode *>(r.self);
! 112: XalanNode& node=vnode.get_node(pool, &method_name);
! 113:
! 114: XalanNode& newChild=as_node(pool, method_name, params, 0, "newChild must be node");
! 115:
! 116: try {
! 117: node.appendChild(&newChild);
! 118: } catch(const XalanDOMException& e) {
! 119: pool.exception()._throw(pool, &method_name, e);
! 120: }
! 121: }
! 122:
! 123: // boolean hasChildNodes();
! 124: static void _hasChildNodes(Request& r, const String& method_name, MethodParams *) {
! 125: Pool& pool=r.pool();
! 126: VXnode& vnode=*static_cast<VXnode *>(r.self);
! 127: XalanNode& node=vnode.get_node(pool, &method_name);
! 128:
! 129: // write out result
! 130: VBool& result=*new(pool) VBool(pool, node.hasChildNodes());
! 131: result.set_name(method_name);
! 132: r.write_no_lang(result);
! 133: }
! 134:
! 135: // Node cloneNode(in boolean deep);
! 136: /// @test 1. who frees it up? 2. ownerDocument=?
! 137: static void _cloneNode(Request& r, const String& method_name, MethodParams *params) {
! 138: Pool& pool=r.pool();
! 139: VXnode& vnode=*static_cast<VXnode *>(r.self);
! 140: XalanNode& node=vnode.get_node(pool, &method_name);
! 141:
! 142: bool deep=params->as_bool(0, "deep must be bool", r);
! 143:
! 144: // write out result
! 145: VXnode& result=*new(pool) VXnode(pool, node.cloneNode(deep));
! 146: result.set_name(method_name);
! 147: r.write_no_lang(result);
! 148: }
! 149:
! 150: // DOM1 element
! 151:
! 152: XalanElement& get_self_element(Request& r, const String& method_name) {
! 153: Pool& pool=r.pool();
! 154: VXnode& vnode=*static_cast<VXnode *>(r.self);
! 155: XalanNode& node=vnode.get_node(pool, &method_name);
! 156:
! 157: if(node.getNodeType()!=XalanNode::ELEMENT_NODE)
! 158: PTHROW(0, 0,
! 159: &method_name,
! 160: "method can be called on node of ELEMENT type");
! 161:
! 162: return *reinterpret_cast<XalanElement *>(&node);
! 163: }
! 164:
! 165: // DOMString getAttribute(in DOMString name);
! 166: static void _getAttribute(Request& r, const String& method_name, MethodParams *params) {
! 167: Pool& pool=r.pool();
! 168: XalanElement& element=get_self_element(r, method_name);
! 169: const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS);
! 170:
! 171: const XalanDOMString& attribute_value=element.getAttribute(XalanDOMString(name));
! 172: // write out result
! 173: r.write_no_lang(*new(pool) VString(pool.transcode(attribute_value)));
! 174: }
! 175:
! 176: // void setAttribute(in DOMString name, in DOMString value) raises(DOMException);
! 177: static void _setAttribute(Request& r, const String& method_name, MethodParams *params) {
! 178: Pool& pool=r.pool();
! 179: XalanElement& element=get_self_element(r, method_name);
! 180: const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS);
! 181: const char *attribute_value=params->as_string(1, "value must not be code").cstr(String::UL_AS_IS);
! 182:
! 183: try {
! 184: element.setAttribute(
! 185: XalanDOMString(name),
! 186: XalanDOMString(attribute_value));
! 187: } catch(const XalanDOMException& e) {
! 188: pool.exception()._throw(pool, &method_name, e);
! 189: }
! 190: }
! 191:
! 192: // void removeAttribute(in DOMString name) raises(DOMException);
! 193: static void _removeAttribute(Request& r, const String& method_name, MethodParams *params) {
! 194: Pool& pool=r.pool();
! 195: XalanElement& element=get_self_element(r, method_name);
! 196: const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS);
! 197:
! 198: try {
! 199: element.removeAttribute(XalanDOMString(name));
! 200: } catch(const XalanDOMException& e) {
! 201: pool.exception()._throw(pool, &method_name, e);
! 202: }
! 203: }
! 204:
! 205: // Attr getAttributeNode(in DOMString name);
! 206: static void _getAttributeNode(Request& r, const String& method_name, MethodParams *params) {
! 207: Pool& pool=r.pool();
! 208: XalanElement& element=get_self_element(r, method_name);
! 209: const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS);
! 210:
! 211: if(XalanAttr *attr=element.getAttributeNode(XalanDOMString(name))) {
! 212: // write out result
! 213: VXnode& result=*new(pool) VXnode(pool, attr);
! 214: r.write_no_lang(result);
! 215: }
! 216: }
! 217:
! 218: // Attr setAttributeNode(in Attr newAttr) raises(DOMException);
! 219: static void _setAttributeNode(Request& r, const String& method_name, MethodParams *params) {
! 220: Pool& pool=r.pool();
! 221: XalanElement& element=get_self_element(r, method_name);
! 222: XalanAttr& newAttr=as_attr(pool, method_name, params, 0, "newAttr must be ATTRIBUTE node");
! 223:
! 224: try {
! 225: if(XalanAttr *returnAttr=element.setAttributeNode(&newAttr)) {
! 226: // write out result
! 227: VXnode& result=*new(pool) VXnode(pool, returnAttr);
! 228: r.write_no_lang(result);
! 229: }
! 230: } catch(const XalanDOMException& e) {
! 231: pool.exception()._throw(pool, &method_name, e);
! 232: }
! 233: }
! 234:
! 235: // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException);
! 236: static void _removeAttributeNode(Request& r, const String& method_name, MethodParams *params) {
! 237: Pool& pool=r.pool();
! 238: XalanElement& element=get_self_element(r, method_name);
! 239: XalanAttr& oldAttr=as_attr(pool, method_name, params, 0, "oldAttr must be ATTRIBUTE node");
! 240:
! 241: try {
! 242: if(XalanAttr *returnAttr=element.removeAttributeNode(&oldAttr)) {
! 243: // write out result
! 244: VXnode& result=*new(pool) VXnode(pool, returnAttr);
! 245: r.write_no_lang(result);
! 246: }
! 247: } catch(const XalanDOMException& e) {
! 248: pool.exception()._throw(pool, &method_name, e);
! 249: }
! 250: }
! 251:
! 252: // NodeList getElementsByTagName(in DOMString name);
! 253: static void _getElementsByTagName(Request& r, const String& method_name, MethodParams *params) {
! 254: Pool& pool=r.pool();
! 255: XalanElement& element=get_self_element(r, method_name);
! 256:
! 257: const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS);
! 258:
! 259: VHash& result=*new(pool) VHash(pool);
! 260: if(const XalanNodeList *nodes=
! 261: element.getElementsByTagName(XalanDOMString(name))) {
! 262: for(int i=0; i<nodes->getLength(); i++) {
! 263: String& skey=*new(pool) String(pool);
! 264: {
! 265: char *buf=(char *)pool.malloc(MAX_NUMBER);
! 266: snprintf(buf, MAX_NUMBER, "%d", i);
! 267: skey << buf;
! 268: }
! 269:
! 270: result.hash().put(skey, new(pool) VXnode(pool, nodes->item(i)));
! 271: }
! 272: }
! 273:
! 274: // write out result
! 275: r.write_no_lang(result);
! 276: }
! 277:
! 278: // void normalize();
! 279: static void _normalize(Request& r, const String& method_name, MethodParams *) {
! 280: XalanElement& element=get_self_element(r, method_name);
! 281:
! 282: element.normalize();
! 283: }
! 284:
! 285:
1.1 parser 286: static void _select(Request& r, const String& method_name, MethodParams *params) {
287: // _asm int 3;
288: Pool& pool=r.pool();
289: VXnode& vnode=*static_cast<VXnode *>(r.self);
290:
291: // expression
292: const String& expression=params->as_string(0, "expression must not be code");
293: const char *expression_cstr=expression.cstr(String::UL_AS_IS);
294: XalanDOMString dstring(expression_cstr);
295: const XalanDOMChar *expression_dcstr=dstring.c_str();
296:
297: XPathEvaluator evaluator;
298: // We'll use these to parse the XML file.
299: XalanSourceTreeDOMSupport dom_support;
300:
301: try {
302: NodeRefList list=evaluator.selectNodeList(dom_support,
303: &vnode.get_node(pool, &method_name),
304: expression_dcstr);
305:
306: VHash& result=*new(pool) VHash(pool);
307: for(int i=0; i<list.getLength(); i++) {
308: String& skey=*new(pool) String(pool);
309: {
310: char *buf=(char *)pool.malloc(MAX_NUMBER);
311: snprintf(buf, MAX_NUMBER, "%d", i);
312: skey << buf;
313: }
314:
315: result.hash().put(skey, new(pool) VXnode(pool, list.item(i)));
316: }
317: result.set_name(method_name);
318: r.write_no_lang(result);
319: } catch(const XSLException& e) {
1.4 parser 320: pool.exception()._throw(pool, &expression, e);
1.1 parser 321: }
322: }
323:
324: static void _select_single(Request& r, const String& method_name, MethodParams *params) {
325: // _asm int 3;
326: Pool& pool=r.pool();
327: VXnode& vnode=*static_cast<VXnode *>(r.self);
328:
329: // expression
330: const String& expression=params->as_string(0, "expression must not be code");
331: const char *expression_cstr=expression.cstr(String::UL_AS_IS);
332: XalanDOMString dstring(expression_cstr);
333: const XalanDOMChar *expression_dcstr=dstring.c_str();
334:
335: XPathEvaluator evaluator;
336: // Initialize the XalanSourceTree subsystem...
337: // XalanSourceTreeInit theSourceTreeInit;
338: // We'll use these to parse the XML file.
339: XalanSourceTreeDOMSupport dom_support;
340:
341: try {
342: if(XalanNode *node=evaluator.selectSingleNode(dom_support,
343: &vnode.get_node(pool, &method_name),
344: expression_dcstr)) {
345:
346: VXnode& result=*new(pool) VXnode(pool, node);
347: result.set_name(method_name);
348: r.write_no_lang(result);
349: }
350: } catch(const XSLException& e) {
1.4 parser 351: pool.exception()._throw(pool, &expression, e);
1.1 parser 352: }
353: }
354:
355: // constructor
356:
1.2 parser 357: MXnode::MXnode(Pool& apool) : Methoded(apool),
358: consts(apool) {
1.1 parser 359: set_name(*NEW String(pool(), XNODE_CLASS_NAME));
1.6 ! parser 360:
! 361: /// DOM1 node
! 362:
! 363: // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException);
! 364: add_native_method("insertBefore", Method::CT_DYNAMIC, _insertBefore, 2, 2);
! 365: // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException);
! 366: add_native_method("replaceChild", Method::CT_DYNAMIC, _replaceChild, 2, 2);
! 367: // Node removeChild(in Node oldChild) raises(DOMException);
! 368: add_native_method("removeChild", Method::CT_DYNAMIC, _removeChild, 1, 1);
! 369: // Node appendChild(in Node newChild) raises(DOMException);
! 370: add_native_method("appendChild", Method::CT_DYNAMIC, _appendChild, 1, 1);
! 371: // boolean hasChildNodes();
! 372: add_native_method("hasChildNodes", Method::CT_DYNAMIC, _hasChildNodes, 0, 0);
! 373: // Node cloneNode(in boolean deep);
! 374: add_native_method("cloneNode", Method::CT_DYNAMIC, _cloneNode, 1, 1);
! 375:
! 376: /// DOM1 element
! 377:
! 378: // DOMString getAttribute(in DOMString name);
! 379: add_native_method("getAttribute", Method::CT_DYNAMIC, _getAttribute, 1, 1);
! 380: // void setAttribute(in DOMString name, in DOMString value) raises(DOMException);
! 381: add_native_method("setAttribute", Method::CT_DYNAMIC, _setAttribute, 2, 2);
! 382: // void removeAttribute(in DOMString name) raises(DOMException);
! 383: add_native_method("removeAttribute", Method::CT_DYNAMIC, _removeAttribute, 1, 1);
! 384: // Attr getAttributeNode(in DOMString name);
! 385: add_native_method("getAttributeNode", Method::CT_DYNAMIC, _getAttributeNode, 1, 1);
! 386: // Attr setAttributeNode(in Attr newAttr) raises(DOMException);
! 387: add_native_method("setAttributeNode", Method::CT_DYNAMIC, _setAttributeNode, 1, 1);
! 388: // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException);
! 389: add_native_method("removeAttributeNode", Method::CT_DYNAMIC, _removeAttributeNode, 1, 1);
! 390: // NodeList getElementsByTagName(in DOMString name);
! 391: add_native_method("getElementsByTagName", Method::CT_DYNAMIC, _getElementsByTagName, 1, 1);
! 392: // void normalize();
! 393: add_native_method("normalize", Method::CT_DYNAMIC, _normalize, 0, 0);
! 394:
! 395: /// parser
1.1 parser 396:
397: // ^node.select[/some/xpath/query] = hash $.#[dnode]
398: add_native_method("select", Method::CT_DYNAMIC, _select, 1, 1);
399:
1.5 parser 400: // ^node.selectSingle[/some/xpath/query] = first dnode
401: add_native_method("selectSingle", Method::CT_DYNAMIC, _select_single, 1, 1);
1.2 parser 402:
403: // consts
404:
405: #define CONST(name, value) \
406: consts.put(*new(pool()) String(pool(), #name), new(pool()) VInt(pool(), value))
407:
408: CONST(ELEMENT_NODE, 1);
409: CONST(ATTRIBUTE_NODE, 2);
410: CONST(TEXT_NODE, 3);
411: CONST(CDATA_SECTION_NODE, 4);
412: CONST(ENTITY_REFERENCE_NODE, 5);
413: CONST(ENTITY_NODE, 6);
414: CONST(PROCESSING_INSTRUCTION_NODE, 7);
415: CONST(COMMENT_NODE, 8);
416: CONST(DOCUMENT_NODE, 9);
417: CONST(DOCUMENT_TYPE_NODE, 10);
418: CONST(DOCUMENT_FRAGMENT_NODE, 11);
419: CONST(NOTATION_NODE, 12);
1.1 parser 420:
421: }
1.3 parser 422:
1.1 parser 423: // global variable
424:
425: Methoded *Xnode_class;
426:
427: #endif
428:
429: // creator
430: Methoded *MXnode_create(Pool& pool) {
431: return
432: #ifdef XML
433: Xnode_class=new(pool) MXnode(pool)
434: #else
435: 0
436: #endif
437: ;
438: }
E-mail: