Annotation of parser3/src/classes/dom.C, revision 1.31
1.2 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.31 ! parser 8: static const char *RCSId="$Id: dom.C,v 1.30 2001/09/21 08:57:30 parser Exp $";
1.2 parser 9:
10: #include "classes.h"
11: #include "pa_request.h"
12: #include "pa_vdom.h"
1.20 parser 13: #include "pa_xslt_stylesheet_manager.h"
14: #include "pa_stylesheet_connection.h"
1.26 parser 15: #include "pa_vfile.h"
1.23 parser 16: #include "dnode.h"
1.2 parser 17:
1.16 parser 18: #include <strstream>
1.2 parser 19: #include <Include/PlatformDefinitions.hpp>
20: #include <util/PlatformUtils.hpp>
21: #include <XalanTransformer/XalanTransformer.hpp>
1.4 parser 22: #include <XalanTransformer/XalanParsedSource.hpp>
1.26 parser 23: #include <XMLSupport/FormatterToXML.hpp>
24: #include <XMLSupport/FormatterToHTML.hpp>
25: #include <XMLSupport/FormatterToText.hpp>
26: #include <XMLSupport/FormatterTreeWalker.hpp>
27: #include <PlatformSupport/XalanFileOutputStream.hpp>
28: #include <PlatformSupport/XalanOutputStreamPrintWriter.hpp>
29: #include <PlatformSupport/DOMStringPrintWriter.hpp>
1.6 parser 30:
1.2 parser 31: // defines
32:
1.4 parser 33: #define DOM_CLASS_NAME "dom"
1.2 parser 34:
1.26 parser 35: #define DOM_OUTPUT_METHOD_OPTION_NAME "method"
36: #define DOM_OUTPUT_METHOD_OPTION_VALUE_XML "xml"
37: #define DOM_OUTPUT_METHOD_OPTION_VALUE_HTML "html"
38: #define DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT "text"
39:
40: #define DOM_OUTPUT_ENCODING_OPTION_NAME "encoding"
41:
42: #define DOM_OUTPUT_DEFAULT_INDENT 4
43:
1.2 parser 44: // class
45:
1.24 parser 46: class MDom : public MDnode {
1.2 parser 47: public: // VStateless_class
1.11 parser 48: Value *create_new_value(Pool& pool) { return new(pool) VDom(pool); }
1.2 parser 49:
50: public:
51: MDom(Pool& pool);
52:
53: public: // Methoded
54: bool used_directly() { return true; }
55: };
56:
57: // methods
58:
1.26 parser 59: class ParserStringXalanOutputStream: public XalanOutputStream {
60: public:
61:
62: explicit ParserStringXalanOutputStream(String& astring) : fstring(astring) {}
63:
64: protected: // XalanOutputStream
65:
66: virtual void writeData(const char *theBuffer, unsigned long theBufferLength) {
67: char *copy=(char *)fstring.malloc((size_t)theBufferLength);
68: memcpy(copy, theBuffer, (size_t)theBufferLength);
69: fstring.APPEND_CLEAN(copy, (size_t)theBufferLength, "dom", -1);
70: }
71:
72: virtual void doFlush() {}
73:
74: private:
75:
76: String& fstring;
77:
78: };
79:
80: static void create_optioned_listener(
81: const char *& content_type, const char *& charset, FormatterListener *& listener,
82: Pool& pool,
83: const String& method_name, MethodParams *params, int index, Writer& writer) {
1.31 ! parser 84: // default encoding from pool
! 85: scharset=pool.get_charset();
1.26 parser 86: const String *method=0;
87: XalanDOMString xalan_encoding;
88:
1.27 parser 89: if(params->size()>index) {
90: Value& voptions=params->as_no_junction(index, "options must not be code");
91: if(voptions.is_defined()) {
92: if(Hash *options=voptions.get_hash()) {
93: // $.method[xml|html|text]
94: if(Value *vmethod=static_cast<Value *>(options->get(*new(pool)
95: String(pool, DOM_OUTPUT_METHOD_OPTION_NAME))))
96: method=&vmethod->as_string();
97:
98: // $.encoding[windows-1251|...]
99: if(Value *vencoding=static_cast<Value *>(options->get(*new(pool)
100: String(pool, DOM_OUTPUT_ENCODING_OPTION_NAME)))) {
1.31 ! parser 101: charset=vencoding->as_string();
! 102: }
1.27 parser 103: } else
104: PTHROW(0, 0,
105: &method_name,
106: "options must be hash");
107: }
1.26 parser 108: }
109:
1.31 ! parser 110: xalan_encoding.append(charset=scharset.cstr());
1.26 parser 111: if(!method/*default='xml'*/ || *method == DOM_OUTPUT_METHOD_OPTION_VALUE_XML) {
112: content_type="text/xml";
113: listener=new FormatterToXML(writer,
114: XalanDOMString(), // version
115: true, // doIndent
116: DOM_OUTPUT_DEFAULT_INDENT, // indent
117: xalan_encoding // encoding
118: );
119: } else if(*method == DOM_OUTPUT_METHOD_OPTION_VALUE_HTML) {
120: content_type="text/html";
121: listener=new FormatterToHTML(writer,
122: xalan_encoding, // encoding
123: XalanDOMString(), // mediaType
124: XalanDOMString(), // doctypeSystem; String to be printed at the top of the document
125: XalanDOMString(), // doctypePublic
126: true, // doIndent
127: DOM_OUTPUT_DEFAULT_INDENT // indent
128: );
129: } else if(*method == DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT) {
130: content_type="text/plain";
131: listener=new FormatterToText(writer,
132: xalan_encoding // encoding
133: );
134: } else
135: PTHROW(0, 0,
136: method,
137: DOM_OUTPUT_METHOD_OPTION_NAME " option is invalid; valid methods are: "
138: "'" DOM_OUTPUT_METHOD_OPTION_VALUE_XML "', "
139: "'" DOM_OUTPUT_METHOD_OPTION_VALUE_HTML "', "
140: "'" DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT "'");
141:
142: // never reached
143: }
144:
145: static void _save(Request& r, const String& method_name, MethodParams *params) {
146: Pool& pool=r.pool();
147: VDnode& vnode=*static_cast<VDnode *>(r.self);
148:
149: // filespec
1.27 parser 150: const String& file_name=params->as_string(0, "file name must not be code");
1.26 parser 151: const char *filespec=r.absolute(file_name).cstr(String::UL_FILE_SPEC);
152:
153: // node
154: XalanNode& node=vnode.get_node(pool, &method_name);
155:
156: try {
157: XalanFileOutputStream stream(XalanDOMString(filespec, strlen(filespec)));
158: XalanOutputStreamPrintWriter writer(stream);
159: const char *content_type, *charset;
160: FormatterListener *formatterListener;
161: create_optioned_listener(content_type, charset, formatterListener,
1.27 parser 162: pool, method_name, params, 1, writer);
1.26 parser 163: FormatterTreeWalker treeWalker(*formatterListener);
164: treeWalker.traverse(&node); // Walk that node and produce the XML...
165: } catch(const XSLException& e) {
1.28 parser 166: r._throw(&method_name, e);
1.26 parser 167: }
168: }
169:
170: static void _string(Request& r, const String& method_name, MethodParams *params) {
171: Pool& pool=r.pool();
172: VDnode& vnode=*static_cast<VDnode *>(r.self);
173:
174: // node
175: XalanNode& node=vnode.get_node(pool, &method_name);
176:
177: try {
178: String parserString=*new(pool) String(pool);
179: ParserStringXalanOutputStream stream(parserString);
180: XalanOutputStreamPrintWriter writer(stream);
181: const char *content_type, *charset;
182: FormatterListener *formatterListener;
183: create_optioned_listener(content_type, charset, formatterListener,
184: pool, method_name, params, 0, writer);
185: FormatterTreeWalker treeWalker(*formatterListener);
186: treeWalker.traverse(&node); // Walk that node and produce the XML...
187:
188: // write out result
189: r.write_no_lang(parserString);
190: } catch(const XSLException& e) {
1.28 parser 191: r._throw(&method_name, e);
1.26 parser 192: }
193: }
194:
195:
196: static void _file(Request& r, const String& method_name, MethodParams *params) {
197: Pool& pool=r.pool();
198: VDnode& vnode=*static_cast<VDnode *>(r.self);
199:
200: // node
201: XalanNode& node=vnode.get_node(pool, &method_name);
202:
203: try {
204: String& parserString=*new(pool) String(pool);
205: ParserStringXalanOutputStream stream(parserString);
206: XalanOutputStreamPrintWriter writer(stream);
207: const char *content_type, *charset;
208: FormatterListener *formatterListener;
209: create_optioned_listener(content_type, charset, formatterListener,
210: pool, method_name, params, 0, writer);
211: FormatterTreeWalker treeWalker(*formatterListener);
212: treeWalker.traverse(&node); // Walk that node and produce the XML...
213:
214: // write out result
215: VFile& vfile=*new(pool) VFile(pool);
216: const char *cstr=parserString.cstr();
217: String *scontent_type=new(pool) String(pool, content_type);
218: Value *vcontent_type;
219: if(charset) {
220: VHash *vhcontent_type=new(pool) VHash(pool);
221: vhcontent_type->hash().put(*value_name, new(pool) VString(*scontent_type));
222: String *scharset=new(pool) String(pool, charset);
223: vhcontent_type->hash().put(*new(pool) String(pool, "charset"), new(pool) VString(*scharset));
224: vcontent_type=vhcontent_type;
225: } else
226: vcontent_type=new(pool) VString(*scontent_type);
227: vfile.set(false/*tainted*/, cstr, strlen(cstr), 0/*file_name*/, vcontent_type);
228: r.write_no_lang(vfile);
229: } catch(const XSLException& e) {
1.28 parser 230: r._throw(&method_name, e);
1.26 parser 231: }
232: }
233:
1.16 parser 234: static void _set(Request& r, const String& method_name, MethodParams *params) {
235: Pool& pool=r.pool();
1.26 parser 236: VDom& vdom=*static_cast<VDom *>(r.self);
1.16 parser 237:
1.17 parser 238: Value& vxml=params->as_junction(0, "xml must be code");
239: Temp_lang temp_lang(r, String::UL_XML);
240: const String& xml=r.process(vxml).as_string();
241:
242: std::istrstream stream(xml.cstr());
1.16 parser 243: XalanParsedSource* parsedSource;
1.26 parser 244: int error=vdom.transformer().parseSource(&stream, parsedSource);
1.16 parser 245:
246: if(error)
247: PTHROW(0, 0,
248: &method_name,
1.26 parser 249: vdom.transformer().getLastError());
1.16 parser 250:
251: // replace any previous parsed source
1.26 parser 252: vdom.set_parsed_source(*parsedSource);
1.16 parser 253: }
254:
1.2 parser 255: static void _load(Request& r, const String& method_name, MethodParams *params) {
256: Pool& pool=r.pool();
1.26 parser 257: VDom& vdom=*static_cast<VDom *>(r.self);
1.2 parser 258:
1.10 parser 259: // filespec
1.20 parser 260: const String& file_name=params->as_string(0, "file name must not be code");
261: const char *filespec=r.absolute(file_name).cstr(String::UL_FILE_SPEC);
1.2 parser 262:
263: XalanParsedSource* parsedSource;
1.26 parser 264: int error=vdom.transformer().parseSource(filespec, parsedSource);
1.2 parser 265:
266: if(error)
267: PTHROW(0, 0,
1.20 parser 268: &file_name,
1.26 parser 269: vdom.transformer().getLastError());
1.2 parser 270:
1.15 parser 271: // replace any previous parsed source
1.26 parser 272: vdom.set_parsed_source(*parsedSource);
1.2 parser 273: }
274:
1.12 parser 275: static void add_xslt_param(const Hash::Key& aattribute, Hash::Val *ameaning,
1.20 parser 276: void *info) {
1.12 parser 277: XalanTransformer& transformer=*static_cast<XalanTransformer *>(info);
278: const char *attribute_cstr=aattribute.cstr();
279: const char *meaning_cstr=static_cast<Value *>(ameaning)->as_string().cstr();
280:
281: transformer.setStylesheetParam(
1.23 parser 282: XalanDOMString(attribute_cstr),
283: XalanDOMString(meaning_cstr));
1.12 parser 284: }
1.10 parser 285: static void _xslt(Request& r, const String& method_name, MethodParams *params) {
286: Pool& pool=r.pool();
1.26 parser 287: VDom& vdom=*static_cast<VDom *>(r.self);
1.10 parser 288:
1.12 parser 289: // params
290: if(params->size()>1) {
1.18 parser 291: Value& vparams=params->as_no_junction(1, "transform parameters parameter must not be code");
1.12 parser 292: if(vparams.is_defined())
293: if(Hash *params=vparams.get_hash())
1.26 parser 294: params->for_each(add_xslt_param, &vdom.transformer());
1.12 parser 295: else
296: PTHROW(0, 0,
297: &method_name,
1.18 parser 298: "transform parameters parameter must be hash");
1.12 parser 299: }
300:
1.10 parser 301: // source
1.26 parser 302: XalanParsedSource &parsed_source=vdom.get_parsed_source(pool, &method_name);
1.10 parser 303:
304: // stylesheet
1.20 parser 305: const String& stylesheet_file_name=params->as_string(0, "file name must not be code");
306: const String& stylesheet_filespec=r.absolute(stylesheet_file_name);
307: //_asm int 3;
308: Stylesheet_connection& connection=XSLT_stylesheet_manager->get_connection(stylesheet_filespec);
1.10 parser 309:
310: // target
1.26 parser 311: XalanDocument* target=vdom.parser_liaison().createDocument();
1.10 parser 312: XSLTResultTarget domResultTarget(target);
313:
314: // transform
1.26 parser 315: int error=vdom.transformer().transform(
1.20 parser 316: parsed_source,
317: &connection.stylesheet(),
318: domResultTarget);
319: connection.close();
1.10 parser 320: if(error)
321: PTHROW(0, 0,
1.20 parser 322: &stylesheet_file_name,
1.26 parser 323: vdom.transformer().getLastError());
1.10 parser 324:
325: // write out result
1.11 parser 326: VDom& result=*new(pool) VDom(pool);
327: result.set_document(*target);
328: r.write_no_lang(result);
1.10 parser 329: }
330:
1.2 parser 331: // constructor
332:
1.24 parser 333: MDom::MDom(Pool& apool) : MDnode(apool) {
1.4 parser 334: set_name(*NEW String(pool(), DOM_CLASS_NAME));
1.26 parser 335:
1.27 parser 336: // ^dom.save[some.xml]
337: // ^dom.save[some.xml;options hash]
338: add_native_method("save", Method::CT_DYNAMIC, _save, 1, 2);
1.26 parser 339:
1.27 parser 340: // ^dom.string[] <doc/>
1.26 parser 341: // ^dom.string[options hash] <doc/>
1.27 parser 342: add_native_method("string", Method::CT_DYNAMIC, _string, 0, 1);
1.26 parser 343:
1.27 parser 344: // ^dom.file[] file with "<doc/>"
1.26 parser 345: // ^dom.file[options hash] file with "<doc/>"
1.27 parser 346: add_native_method("file", Method::CT_DYNAMIC, _file, 0, 1);
1.16 parser 347:
348: // ^dom::set[<some>xml</some>]
349: add_native_method("set", Method::CT_DYNAMIC, _set, 1, 1);
1.2 parser 350:
1.3 parser 351: // ^dom::load[some.xml]
1.2 parser 352: add_native_method("load", Method::CT_DYNAMIC, _load, 1, 1);
1.10 parser 353:
1.20 parser 354: // ^dom.xslt[stylesheet file_name]
355: // ^dom.xslt[stylesheet file_name;params hash]
1.12 parser 356: add_native_method("xslt", Method::CT_DYNAMIC, _xslt, 1, 2);
1.6 parser 357:
1.2 parser 358: }
359: // global variable
360:
361: Methoded *Dom_class;
362:
363: // creator
364:
365: Methoded *MDom_create(Pool& pool) {
366: return Dom_class=new(pool) MDom(pool);
367: }
E-mail: