Annotation of parser3/src/classes/dnode.C, revision 1.2
1.1 parser 1: /** @file
2: Parser: @b dom parser class.
3:
4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
5:
6: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
7: */
1.2 ! parser 8: static const char *RCSId="$Id: dnode.C,v 1.1 2001/09/18 12:25:06 parser Exp $";
1.1 parser 9:
10: #if _MSC_VER
11: # pragma warning(disable:4291) // disable warning
12: // "no matching operator delete found; memory will not be freed if initialization throws an exception
13: #endif
14:
15: #include "classes.h"
16: #include "pa_request.h"
17: #include "pa_vdnode.h"
1.2 ! parser 18: #include "pa_vfile.h"
! 19:
1.1 parser 20: #include "dnode.h"
21:
22: #include <util/XMLString.hpp>
23: //#include <XalanSourceTree/XalanSourceTreeInit.hpp>
24: #include <XalanSourceTree/XalanSourceTreeDOMSupport.hpp>
25: #include <XPath/XPathEvaluator.hpp>
26: #include <XPath/NodeRefList.hpp>
1.2 ! parser 27: #include <XMLSupport/FormatterToXML.hpp>
! 28: #include <XMLSupport/FormatterToHTML.hpp>
! 29: #include <XMLSupport/FormatterToText.hpp>
! 30: #include <XMLSupport/FormatterTreeWalker.hpp>
! 31: #include <PlatformSupport/XalanFileOutputStream.hpp>
! 32: #include <PlatformSupport/XalanOutputStreamPrintWriter.hpp>
! 33: #include <PlatformSupport/DOMStringPrintWriter.hpp>
1.1 parser 34:
35: // defines
36:
37: #define DNODE_CLASS_NAME "dnode"
38:
1.2 ! parser 39: #define DOM_OUTPUT_METHOD_OPTION_NAME "method"
! 40: #define DOM_OUTPUT_METHOD_OPTION_VALUE_XML "xml"
! 41: #define DOM_OUTPUT_METHOD_OPTION_VALUE_HTML "html"
! 42: #define DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT "text"
! 43:
! 44: #define DOM_OUTPUT_ENCODING_OPTION_NAME "encoding"
! 45:
! 46: #define DOM_OUTPUT_DEFAULT_INDENT 4
! 47:
1.1 parser 48: // class
49:
50: // methods
51:
1.2 ! parser 52: class ParserStringXalanOutputStream: public XalanOutputStream {
! 53: public:
! 54:
! 55: explicit ParserStringXalanOutputStream(String& astring) : fstring(astring) {}
! 56:
! 57: protected: // XalanOutputStream
! 58:
! 59: virtual void writeData(const char *theBuffer, unsigned long theBufferLength) {
! 60: char *copy=(char *)fstring.malloc((size_t)theBufferLength);
! 61: memcpy(copy, theBuffer, (size_t)theBufferLength);
! 62: fstring.APPEND_CLEAN(copy, (size_t)theBufferLength, "dom", -1);
! 63: }
! 64:
! 65: virtual void doFlush() {}
! 66:
! 67: private:
! 68:
! 69: String& fstring;
! 70:
! 71: };
! 72:
! 73: static void create_optioned_listener(
! 74: const char *& content_type, const char *& charset, FormatterListener *& listener,
! 75: Pool& pool,
! 76: const String& method_name, MethodParams *params, int index, Writer& writer) {
! 77: charset=0;
! 78: const String *method=0;
! 79: XalanDOMString xalan_encoding;
! 80:
! 81: Value& voptions=params->as_no_junction(index, "options must not be code");
! 82: if(voptions.is_defined()) {
! 83: if(Hash *options=voptions.get_hash()) {
! 84: // $.method[xml|html|text]
! 85: if(Value *vmethod=static_cast<Value *>(options->get(*new(pool)
! 86: String(pool, DOM_OUTPUT_METHOD_OPTION_NAME))))
! 87: method=&vmethod->as_string();
! 88:
! 89: // $.encoding[windows-1251|...]
! 90: if(Value *vencoding=static_cast<Value *>(options->get(*new(pool)
! 91: String(pool, DOM_OUTPUT_ENCODING_OPTION_NAME)))) {
! 92: charset=vencoding->as_string().cstr();
! 93: xalan_encoding.append(charset, strlen(charset));
! 94: }
! 95: } else
! 96: PTHROW(0, 0,
! 97: &method_name,
! 98: "options must be hash");
! 99: }
! 100:
! 101: if(!method/*default='xml'*/ || *method == DOM_OUTPUT_METHOD_OPTION_VALUE_XML) {
! 102: content_type="text/xml";
! 103: listener=new FormatterToXML(writer,
! 104: XalanDOMString(), // version
! 105: true, // doIndent
! 106: DOM_OUTPUT_DEFAULT_INDENT, // indent
! 107: xalan_encoding // encoding
! 108: );
! 109: } else if(*method == DOM_OUTPUT_METHOD_OPTION_VALUE_HTML) {
! 110: content_type="text/html";
! 111: listener=new FormatterToHTML(writer,
! 112: xalan_encoding, // encoding
! 113: XalanDOMString(), // mediaType
! 114: XalanDOMString(), // doctypeSystem; String to be printed at the top of the document
! 115: XalanDOMString(), // doctypePublic
! 116: true, // doIndent
! 117: DOM_OUTPUT_DEFAULT_INDENT // indent
! 118: );
! 119: } else if(*method == DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT) {
! 120: content_type="text/plain";
! 121: listener=new FormatterToText(writer,
! 122: xalan_encoding // encoding
! 123: );
! 124: } else
! 125: PTHROW(0, 0,
! 126: method,
! 127: DOM_OUTPUT_METHOD_OPTION_NAME " option is invalid; valid methods are: "
! 128: "'" DOM_OUTPUT_METHOD_OPTION_VALUE_XML "', "
! 129: "'" DOM_OUTPUT_METHOD_OPTION_VALUE_HTML "', "
! 130: "'" DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT "'");
! 131:
! 132: // never reached
! 133: }
! 134:
! 135: static void _save(Request& r, const String& method_name, MethodParams *params) {
! 136: Pool& pool=r.pool();
! 137: VDnode& vnode=*static_cast<VDnode *>(r.self);
! 138:
! 139: // filespec
! 140: const String& file_name=params->as_string(1, "file name must not be code");
! 141: const char *filespec=r.absolute(file_name).cstr(String::UL_FILE_SPEC);
! 142:
! 143: // node
! 144: XalanNode& node=vnode.get_node(pool, &method_name);
! 145:
! 146: try {
! 147: XalanFileOutputStream stream(XalanDOMString(filespec, strlen(filespec)));
! 148: XalanOutputStreamPrintWriter writer(stream);
! 149: const char *content_type, *charset;
! 150: FormatterListener *formatterListener;
! 151: create_optioned_listener(content_type, charset, formatterListener,
! 152: pool, method_name, params, 0, writer);
! 153: FormatterTreeWalker treeWalker(*formatterListener);
! 154: treeWalker.traverse(&node); // Walk that node and produce the XML...
! 155: } catch(const XSLException& e) {
! 156: _throw(pool, &method_name, e);
! 157: }
! 158: }
! 159:
! 160: static void _string(Request& r, const String& method_name, MethodParams *params) {
! 161: Pool& pool=r.pool();
! 162: VDnode& vnode=*static_cast<VDnode *>(r.self);
! 163:
! 164: // node
! 165: XalanNode& node=vnode.get_node(pool, &method_name);
! 166:
! 167: try {
! 168: String parserString=*new(pool) String(pool);
! 169: ParserStringXalanOutputStream stream(parserString);
! 170: XalanOutputStreamPrintWriter writer(stream);
! 171: const char *content_type, *charset;
! 172: FormatterListener *formatterListener;
! 173: create_optioned_listener(content_type, charset, formatterListener,
! 174: pool, method_name, params, 0, writer);
! 175: FormatterTreeWalker treeWalker(*formatterListener);
! 176: treeWalker.traverse(&node); // Walk that node and produce the XML...
! 177:
! 178: // write out result
! 179: r.write_no_lang(parserString);
! 180: } catch(const XSLException& e) {
! 181: _throw(pool, &method_name, e);
! 182: }
! 183: }
! 184:
! 185:
! 186: static void _file(Request& r, const String& method_name, MethodParams *params) {
! 187: Pool& pool=r.pool();
! 188: VDnode& vnode=*static_cast<VDnode *>(r.self);
! 189:
! 190: // node
! 191: XalanNode& node=vnode.get_node(pool, &method_name);
! 192:
! 193: try {
! 194: String& parserString=*new(pool) String(pool);
! 195: ParserStringXalanOutputStream stream(parserString);
! 196: XalanOutputStreamPrintWriter writer(stream);
! 197: const char *content_type, *charset;
! 198: FormatterListener *formatterListener;
! 199: create_optioned_listener(content_type, charset, formatterListener,
! 200: pool, method_name, params, 0, writer);
! 201: FormatterTreeWalker treeWalker(*formatterListener);
! 202: treeWalker.traverse(&node); // Walk that node and produce the XML...
! 203:
! 204: // write out result
! 205: VFile& vfile=*new(pool) VFile(pool);
! 206: const char *cstr=parserString.cstr();
! 207: String *scontent_type=new(pool) String(pool, content_type);
! 208: Value *vcontent_type;
! 209: if(charset) {
! 210: VHash *vhcontent_type=new(pool) VHash(pool);
! 211: vhcontent_type->hash().put(*value_name, new(pool) VString(*scontent_type));
! 212: String *scharset=new(pool) String(pool, charset);
! 213: vhcontent_type->hash().put(*new(pool) String(pool, "charset"), new(pool) VString(*scharset));
! 214: vcontent_type=vhcontent_type;
! 215: } else
! 216: vcontent_type=new(pool) VString(*scontent_type);
! 217: vfile.set(false/*tainted*/, cstr, strlen(cstr), 0/*file_name*/, vcontent_type);
! 218: r.write_no_lang(vfile);
! 219: } catch(const XSLException& e) {
! 220: _throw(pool, &method_name, e);
! 221: }
! 222: }
! 223:
! 224:
1.1 parser 225: static void _xpath(Request& r, const String& method_name, MethodParams *params) {
226: // _asm int 3;
227: Pool& pool=r.pool();
1.2 ! parser 228: VDnode& vnode=*static_cast<VDnode *>(r.self);
1.1 parser 229:
230: // expression
231: const String& expression=params->as_string(0, "expression must not be code");
232: const char *expression_cstr=expression.cstr(String::UL_AS_IS);
233: XalanDOMString dstring(expression_cstr);
234: const XalanDOMChar *expression_dcstr=dstring.c_str();
235:
236: XPathEvaluator evaluator;
237: // Initialize the XalanSourceTree subsystem...
238: // XalanSourceTreeInit theSourceTreeInit;
239: // We'll use these to parse the XML file.
240: XalanSourceTreeDOMSupport dom_support;
241:
242: try {
243: NodeRefList list=evaluator.selectNodeList(dom_support,
1.2 ! parser 244: &vnode.get_node(pool, &method_name),
1.1 parser 245: expression_dcstr);
246:
247: VHash& result=*new(pool) VHash(pool);
248: for(int i=0; i<list.getLength(); i++) {
249: String& skey=*new(pool) String(pool);
250: {
251: char *buf=(char *)pool.malloc(MAX_NUMBER);
252: snprintf(buf, MAX_NUMBER, "%d", i);
253: skey << buf;
254: }
255:
256: result.hash().put(skey, new(pool) VDnode(pool, list.item(i)));
257: }
258: result.set_name(method_name);
259: r.write_no_lang(result);
260: } catch(const XSLException& e) {
261: _throw(pool, &expression, e);
262: }
263: }
264:
265: // constructor
266:
267: MDnode::MDnode(Pool& apool) : Methoded(apool) {
268: set_name(*NEW String(pool(), DNODE_CLASS_NAME));
1.2 ! parser 269:
! 270: // ^node.save[options hash;some.xml]
! 271: add_native_method("save", Method::CT_DYNAMIC, _save, 2, 2);
! 272:
! 273: // ^node.string[options hash] <doc/>
! 274: add_native_method("string", Method::CT_DYNAMIC, _string, 1, 1);
! 275:
! 276: // ^node.file[options hash] file with "<doc/>"
! 277: add_native_method("file", Method::CT_DYNAMIC, _file, 1, 1);
1.1 parser 278:
279: // ^node.xpath[/some/xpath/query]
280: add_native_method("xpath", Method::CT_DYNAMIC, _xpath, 1, 1);
281:
282: }
283: // global variable
284:
285: Methoded *Dnode_class;
286:
287: // creator
288:
289: Methoded *MDnode_create(Pool& pool) {
290: return Dnode_class=new(pool) MDnode(pool);
291: }
E-mail: