Annotation of parser3/src/classes/xnode.C, revision 1.8
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.8 ! parser 7: $Id: xnode.C,v 1.7 2001/10/16 14:43:30 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 {
1.8 ! parser 242: /*XalanAttr *returnAttr*/element.removeAttributeNode(&oldAttr);
1.6 parser 243: } catch(const XalanDOMException& e) {
244: pool.exception()._throw(pool, &method_name, e);
245: }
246: }
247:
248: // NodeList getElementsByTagName(in DOMString name);
249: static void _getElementsByTagName(Request& r, const String& method_name, MethodParams *params) {
250: Pool& pool=r.pool();
251: XalanElement& element=get_self_element(r, method_name);
252:
253: const char *name=params->as_string(0, "name must not be code").cstr(String::UL_AS_IS);
254:
255: VHash& result=*new(pool) VHash(pool);
256: if(const XalanNodeList *nodes=
257: element.getElementsByTagName(XalanDOMString(name))) {
258: for(int i=0; i<nodes->getLength(); i++) {
259: String& skey=*new(pool) String(pool);
260: {
261: char *buf=(char *)pool.malloc(MAX_NUMBER);
262: snprintf(buf, MAX_NUMBER, "%d", i);
263: skey << buf;
264: }
265:
266: result.hash().put(skey, new(pool) VXnode(pool, nodes->item(i)));
267: }
268: }
269:
270: // write out result
271: r.write_no_lang(result);
272: }
273:
274: // void normalize();
275: static void _normalize(Request& r, const String& method_name, MethodParams *) {
276: XalanElement& element=get_self_element(r, method_name);
277:
278: element.normalize();
279: }
280:
281:
1.1 parser 282: static void _select(Request& r, const String& method_name, MethodParams *params) {
283: // _asm int 3;
284: Pool& pool=r.pool();
285: VXnode& vnode=*static_cast<VXnode *>(r.self);
286:
287: // expression
288: const String& expression=params->as_string(0, "expression must not be code");
289: const char *expression_cstr=expression.cstr(String::UL_AS_IS);
290: XalanDOMString dstring(expression_cstr);
291: const XalanDOMChar *expression_dcstr=dstring.c_str();
292:
293: XPathEvaluator evaluator;
294: // We'll use these to parse the XML file.
295: XalanSourceTreeDOMSupport dom_support;
296:
297: try {
298: NodeRefList list=evaluator.selectNodeList(dom_support,
299: &vnode.get_node(pool, &method_name),
300: expression_dcstr);
301:
302: VHash& result=*new(pool) VHash(pool);
303: for(int i=0; i<list.getLength(); i++) {
304: String& skey=*new(pool) String(pool);
305: {
306: char *buf=(char *)pool.malloc(MAX_NUMBER);
307: snprintf(buf, MAX_NUMBER, "%d", i);
308: skey << buf;
309: }
310:
311: result.hash().put(skey, new(pool) VXnode(pool, list.item(i)));
312: }
313: result.set_name(method_name);
314: r.write_no_lang(result);
315: } catch(const XSLException& e) {
1.4 parser 316: pool.exception()._throw(pool, &expression, e);
1.1 parser 317: }
318: }
319:
320: static void _select_single(Request& r, const String& method_name, MethodParams *params) {
321: // _asm int 3;
322: Pool& pool=r.pool();
323: VXnode& vnode=*static_cast<VXnode *>(r.self);
324:
325: // expression
326: const String& expression=params->as_string(0, "expression must not be code");
327: const char *expression_cstr=expression.cstr(String::UL_AS_IS);
328: XalanDOMString dstring(expression_cstr);
329: const XalanDOMChar *expression_dcstr=dstring.c_str();
330:
331: XPathEvaluator evaluator;
332: // Initialize the XalanSourceTree subsystem...
333: // XalanSourceTreeInit theSourceTreeInit;
334: // We'll use these to parse the XML file.
335: XalanSourceTreeDOMSupport dom_support;
336:
337: try {
338: if(XalanNode *node=evaluator.selectSingleNode(dom_support,
339: &vnode.get_node(pool, &method_name),
340: expression_dcstr)) {
341:
342: VXnode& result=*new(pool) VXnode(pool, node);
343: result.set_name(method_name);
344: r.write_no_lang(result);
345: }
346: } catch(const XSLException& e) {
1.4 parser 347: pool.exception()._throw(pool, &expression, e);
1.1 parser 348: }
349: }
350:
351: // constructor
352:
1.2 parser 353: MXnode::MXnode(Pool& apool) : Methoded(apool),
354: consts(apool) {
1.1 parser 355: set_name(*NEW String(pool(), XNODE_CLASS_NAME));
1.6 parser 356:
357: /// DOM1 node
358:
359: // Node insertBefore(in Node newChild,in Node refChild) raises(DOMException);
360: add_native_method("insertBefore", Method::CT_DYNAMIC, _insertBefore, 2, 2);
361: // Node replaceChild(in Node newChild,in Node oldChild) raises(DOMException);
362: add_native_method("replaceChild", Method::CT_DYNAMIC, _replaceChild, 2, 2);
363: // Node removeChild(in Node oldChild) raises(DOMException);
364: add_native_method("removeChild", Method::CT_DYNAMIC, _removeChild, 1, 1);
365: // Node appendChild(in Node newChild) raises(DOMException);
366: add_native_method("appendChild", Method::CT_DYNAMIC, _appendChild, 1, 1);
367: // boolean hasChildNodes();
368: add_native_method("hasChildNodes", Method::CT_DYNAMIC, _hasChildNodes, 0, 0);
369: // Node cloneNode(in boolean deep);
370: add_native_method("cloneNode", Method::CT_DYNAMIC, _cloneNode, 1, 1);
371:
372: /// DOM1 element
373:
374: // DOMString getAttribute(in DOMString name);
375: add_native_method("getAttribute", Method::CT_DYNAMIC, _getAttribute, 1, 1);
376: // void setAttribute(in DOMString name, in DOMString value) raises(DOMException);
377: add_native_method("setAttribute", Method::CT_DYNAMIC, _setAttribute, 2, 2);
378: // void removeAttribute(in DOMString name) raises(DOMException);
379: add_native_method("removeAttribute", Method::CT_DYNAMIC, _removeAttribute, 1, 1);
380: // Attr getAttributeNode(in DOMString name);
381: add_native_method("getAttributeNode", Method::CT_DYNAMIC, _getAttributeNode, 1, 1);
382: // Attr setAttributeNode(in Attr newAttr) raises(DOMException);
383: add_native_method("setAttributeNode", Method::CT_DYNAMIC, _setAttributeNode, 1, 1);
384: // Attr removeAttributeNode(in Attr oldAttr) raises(DOMException);
385: add_native_method("removeAttributeNode", Method::CT_DYNAMIC, _removeAttributeNode, 1, 1);
386: // NodeList getElementsByTagName(in DOMString name);
387: add_native_method("getElementsByTagName", Method::CT_DYNAMIC, _getElementsByTagName, 1, 1);
388: // void normalize();
389: add_native_method("normalize", Method::CT_DYNAMIC, _normalize, 0, 0);
390:
391: /// parser
1.1 parser 392:
393: // ^node.select[/some/xpath/query] = hash $.#[dnode]
394: add_native_method("select", Method::CT_DYNAMIC, _select, 1, 1);
395:
1.5 parser 396: // ^node.selectSingle[/some/xpath/query] = first dnode
397: add_native_method("selectSingle", Method::CT_DYNAMIC, _select_single, 1, 1);
1.2 parser 398:
399: // consts
400:
401: #define CONST(name, value) \
402: consts.put(*new(pool()) String(pool(), #name), new(pool()) VInt(pool(), value))
403:
404: CONST(ELEMENT_NODE, 1);
405: CONST(ATTRIBUTE_NODE, 2);
406: CONST(TEXT_NODE, 3);
407: CONST(CDATA_SECTION_NODE, 4);
408: CONST(ENTITY_REFERENCE_NODE, 5);
409: CONST(ENTITY_NODE, 6);
410: CONST(PROCESSING_INSTRUCTION_NODE, 7);
411: CONST(COMMENT_NODE, 8);
412: CONST(DOCUMENT_NODE, 9);
413: CONST(DOCUMENT_TYPE_NODE, 10);
414: CONST(DOCUMENT_FRAGMENT_NODE, 11);
415: CONST(NOTATION_NODE, 12);
1.1 parser 416:
417: }
1.3 parser 418:
1.1 parser 419: // global variable
420:
421: Methoded *Xnode_class;
422:
423: #endif
424:
425: // creator
426: Methoded *MXnode_create(Pool& pool) {
427: return
428: #ifdef XML
429: Xnode_class=new(pool) MXnode(pool)
430: #else
431: 0
432: #endif
433: ;
434: }
E-mail: