Annotation of parser3/src/classes/dom.C, revision 1.15
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.15 ! parser 8: static const char *RCSId="$Id: dom.C,v 1.14 2001/09/11 08:39:04 parser Exp $";
1.2 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_vdom.h"
1.9 parser 18: #include "pa_vfile.h"
1.2 parser 19:
20: #include <Include/PlatformDefinitions.hpp>
21: #include <util/PlatformUtils.hpp>
1.5 parser 22: #include <util/XMLString.hpp>
1.2 parser 23: #include <XalanTransformer/XalanTransformer.hpp>
1.4 parser 24: #include <XalanTransformer/XalanParsedSource.hpp>
1.11 parser 25: //#include <XalanTransformer/XercesDOMParsedSource.hpp>
1.4 parser 26: #include <PlatformSupport/XalanFileOutputStream.hpp>
27: #include <PlatformSupport/XalanOutputStreamPrintWriter.hpp>
1.6 parser 28: #include <PlatformSupport/DOMStringPrintWriter.hpp>
1.4 parser 29: #include <XMLSupport/FormatterToXML.hpp>
1.13 parser 30: #include <XMLSupport/FormatterToHTML.hpp>
31: #include <XMLSupport/FormatterToText.hpp>
1.4 parser 32: #include <XMLSupport/FormatterTreeWalker.hpp>
1.11 parser 33: //#include <XercesParserLiaison/XercesDOMSupport.hpp>
1.6 parser 34:
1.2 parser 35: // defines
36:
1.4 parser 37: #define DOM_CLASS_NAME "dom"
1.2 parser 38:
1.13 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.2 parser 48: // class
49:
50: class MDom : public Methoded {
51: public: // VStateless_class
1.11 parser 52: Value *create_new_value(Pool& pool) { return new(pool) VDom(pool); }
1.2 parser 53:
54: public:
55: MDom(Pool& pool);
56:
57: public: // Methoded
58: bool used_directly() { return true; }
59: };
60:
61: // methods
62:
63: static void _load(Request& r, const String& method_name, MethodParams *params) {
64: Pool& pool=r.pool();
1.10 parser 65: VDom& vDom=*static_cast<VDom *>(r.self);
1.2 parser 66:
1.10 parser 67: // filespec
1.2 parser 68: const String& filename=params->as_string(0, "file name must not be code");
69: const char *filespec=r.absolute(filename).cstr(String::UL_FILE_NAME);
70:
71: XalanParsedSource* parsedSource;
1.15 ! parser 72: int error=vDom.get_transformer().parseSource(filespec, parsedSource);
1.2 parser 73:
74: if(error)
75: PTHROW(0, 0,
76: &filename,
1.10 parser 77: vDom.get_transformer().getLastError());
1.2 parser 78:
1.15 ! parser 79: // replace any previous parsed source
1.11 parser 80: vDom.set_parsed_source(*parsedSource);
1.2 parser 81: }
82:
1.5 parser 83: const char *strX(const XalanDOMString& s) {
84: return XMLString::transcode(s.c_str());
85: }
86:
87: static void _throw(Pool& pool, const String *source, const XSLException& e) {
88: if(e.getURI().empty())
89: PTHROW(0, 0,
90: source,
91: "%s (%s)",
92: strX(e.getMessage()), // message for exception
93: strX(e.getType()) // type of exception
94: );
95: else
96: PTHROW(0, 0,
97: source,
98: "%s (%s) %s(%d:%d)'",
99: strX(e.getMessage()), // message for exception
100: strX(e.getType()), // type of exception
101:
102: strX(e.getURI()), // URI for the associated document, if any
103: e.getLineNumber(), // line number, or -1 if unknown
104: e.getColumnNumber() // column number, or -1 if unknown
105: );
106: }
107:
1.6 parser 108: class ParserStringOutputStream: public XalanOutputStream {
109: public:
110:
1.7 parser 111: explicit ParserStringOutputStream(String& astring) : fstring(astring) {}
112:
113: protected: // XalanOutputStream
114:
115: virtual void writeData(const char *theBuffer, unsigned long theBufferLength) {
1.6 parser 116: char *copy=(char *)fstring.malloc((size_t)theBufferLength);
117: memcpy(copy, theBuffer, (size_t)theBufferLength);
118: fstring.APPEND_CLEAN(copy, (size_t)theBufferLength, "dom", -1);
119: }
120:
1.7 parser 121: virtual void doFlush() {}
1.6 parser 122:
123: private:
124:
125: String& fstring;
126:
127: };
128:
129:
1.13 parser 130: FormatterListener *create_optioned_listener(Pool& pool,
131: const String& method_name, MethodParams *params, int index,
132: Writer& writer) {
133: const String *method=0;
134: XalanDOMString xalan_encoding;
135:
136: Value& voptions=params->as_no_junction(index, "options must not be code");
137: if(voptions.is_defined()) {
138: if(Hash *options=voptions.get_hash()) {
139: // $.method[xml|html|text]
1.15 ! parser 140: if(Value *vmethod=static_cast<Value *>(options->get(*new(pool)
! 141: String(pool, DOM_OUTPUT_METHOD_OPTION_NAME))))
! 142: method=&vmethod->as_string();
1.13 parser 143:
144: // $.encoding[windows-1251|...]
145: if(Value *vencoding=static_cast<Value *>(options->get(*new(pool)
146: String(pool, DOM_OUTPUT_ENCODING_OPTION_NAME)))) {
147: const char *cstr=vencoding->as_string().cstr();
148: xalan_encoding.append(cstr, strlen(cstr));
149: }
150: } else
151: PTHROW(0, 0,
152: &method_name,
153: "params must be hash");
154: }
155:
156: if(!method/*default='xml'*/ || *method == DOM_OUTPUT_METHOD_OPTION_VALUE_XML)
157: return new FormatterToXML(writer,
158: XalanDOMString(), // version
159: true, // doIndent
160: DOM_OUTPUT_DEFAULT_INDENT, // indent
161: xalan_encoding // encoding
162: );
163: else if(*method == DOM_OUTPUT_METHOD_OPTION_VALUE_HTML)
164: return new FormatterToHTML(writer,
165: xalan_encoding, // encoding
166: XalanDOMString(), // mediaType
167: XalanDOMString(), // doctypeSystem; String to be printed at the top of the document
168: XalanDOMString(), // doctypePublic
169: true, // doIndent
170: DOM_OUTPUT_DEFAULT_INDENT // indent
171: );
172: else if(*method == DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT)
173: return new FormatterToText(writer,
174: xalan_encoding // encoding
175: );
176: else
177: PTHROW(0, 0,
178: method,
1.14 parser 179: DOM_OUTPUT_METHOD_OPTION_NAME " option is invalid; valid methods are: "
180: "'" DOM_OUTPUT_METHOD_OPTION_VALUE_XML "', "
181: "'" DOM_OUTPUT_METHOD_OPTION_VALUE_HTML "', "
1.13 parser 182: "'" DOM_OUTPUT_METHOD_OPTION_VALUE_TEXT "'");
183:
184: // never reached
185: return 0; // calm, compiler
186: }
187:
1.3 parser 188: static void _save(Request& r, const String& method_name, MethodParams *params) {
189: Pool& pool=r.pool();
1.10 parser 190: VDom& vDom=*static_cast<VDom *>(r.self);
1.3 parser 191:
192: // filespec
1.7 parser 193: const String& filename=params->as_string(1, "file name must not be code");
1.3 parser 194: const char *filespec=r.absolute(filename).cstr(String::UL_FILE_NAME);
195:
1.11 parser 196: // document
197: XalanDocument& document=vDom.get_document(pool, &method_name);
1.3 parser 198:
1.5 parser 199: try {
1.6 parser 200: XalanFileOutputStream stream(XalanDOMString(filespec, strlen(filespec)));
201: XalanOutputStreamPrintWriter writer(stream);
1.13 parser 202: FormatterListener& formatterListener=*create_optioned_listener(pool, method_name, params, 0,
203: writer);
1.6 parser 204: FormatterTreeWalker treeWalker(formatterListener);
1.11 parser 205: treeWalker.traverse(&document); // Walk the document and produce the XML...
1.6 parser 206: } catch(const XSLException& e) {
207: _throw(pool, &method_name, e);
208: }
209: }
210:
211: static void _string(Request& r, const String& method_name, MethodParams *params) {
212: Pool& pool=r.pool();
1.10 parser 213: VDom& vDom=*static_cast<VDom *>(r.self);
1.6 parser 214:
1.11 parser 215: // document
216: XalanDocument& document=vDom.get_document(pool, &method_name);
1.6 parser 217:
218: try {
1.9 parser 219: String parserString=*new(pool) String(pool);
220: ParserStringOutputStream stream(parserString);
1.6 parser 221: XalanOutputStreamPrintWriter writer(stream);
1.13 parser 222: FormatterListener& formatterListener=*create_optioned_listener(pool, method_name, params, 0,
223: writer);
1.6 parser 224: FormatterTreeWalker treeWalker(formatterListener);
1.11 parser 225: treeWalker.traverse(&document); // Walk the document and produce the XML...
1.6 parser 226:
227: // write out result
1.9 parser 228: r.write_no_lang(parserString);
1.5 parser 229: } catch(const XSLException& e) {
230: _throw(pool, &method_name, e);
231: }
1.3 parser 232: }
233:
1.9 parser 234:
235: static void _file(Request& r, const String& method_name, MethodParams *params) {
236: Pool& pool=r.pool();
1.10 parser 237: VDom& vDom=*static_cast<VDom *>(r.self);
1.9 parser 238:
1.11 parser 239: // document
240: XalanDocument& document=vDom.get_document(pool, &method_name);
1.9 parser 241:
242: try {
243: String& parserString=*new(pool) String(pool);
244: ParserStringOutputStream stream(parserString);
245: XalanOutputStreamPrintWriter writer(stream);
1.13 parser 246: FormatterListener& formatterListener=*create_optioned_listener(pool, method_name, params, 0,
247: writer);
1.9 parser 248: FormatterTreeWalker treeWalker(formatterListener);
1.11 parser 249: treeWalker.traverse(&document); // Walk the document and produce the XML...
1.9 parser 250:
251: // write out result
252: VFile& vfile=*new(pool) VFile(pool);
253: const char *cstr=parserString.cstr();
254: vfile.set(false/*tainted*/, cstr, strlen(cstr), 0/*filename*/, new(pool) String(pool, "text/xml"));
255: r.write_no_lang(vfile);
256: } catch(const XSLException& e) {
257: _throw(pool, &method_name, e);
258: }
259: }
260:
261:
1.12 parser 262: static void add_xslt_param(const Hash::Key& aattribute, Hash::Val *ameaning,
263: void *info) {
264: XalanTransformer& transformer=*static_cast<XalanTransformer *>(info);
265: const char *attribute_cstr=aattribute.cstr();
266: const char *meaning_cstr=static_cast<Value *>(ameaning)->as_string().cstr();
267:
268: transformer.setStylesheetParam(
269: XalanDOMString(attribute_cstr, strlen(attribute_cstr)),
270: XalanDOMString(meaning_cstr, strlen(meaning_cstr)));
271: }
1.10 parser 272: static void _xslt(Request& r, const String& method_name, MethodParams *params) {
273: Pool& pool=r.pool();
274: VDom& vDom=*static_cast<VDom *>(r.self);
275:
1.12 parser 276: // params
277: if(params->size()>1) {
278: Value& vparams=params->as_no_junction(1, "params must not be code");
279: if(vparams.is_defined())
280: if(Hash *params=vparams.get_hash())
281: params->for_each(add_xslt_param, &vDom.get_transformer());
282: else
283: PTHROW(0, 0,
284: &method_name,
285: "params must be hash");
286: }
287:
1.10 parser 288: // source
1.11 parser 289: XalanParsedSource &parsed_source=vDom.get_parsed_source(pool, &method_name);
1.10 parser 290:
291: // stylesheet
292: const String& stylesheet_filename=params->as_string(0, "file name must not be code");
293: const char *stylesheet_filespec=r.absolute(stylesheet_filename).cstr(String::UL_FILE_NAME);
294:
295: // target
1.11 parser 296: XalanDocument* target=vDom.get_parser_liaison().createDocument();
1.10 parser 297: XSLTResultTarget domResultTarget(target);
298:
299: // transform
1.11 parser 300: int error=vDom.get_transformer().transform(parsed_source, stylesheet_filespec, domResultTarget);
1.10 parser 301: if(error)
302: PTHROW(0, 0,
303: &stylesheet_filename,
304: vDom.get_transformer().getLastError());
305:
306: // write out result
1.11 parser 307: VDom& result=*new(pool) VDom(pool);
308: result.set_document(*target);
309: r.write_no_lang(result);
1.10 parser 310: }
311:
1.2 parser 312: // constructor
313:
314: MDom::MDom(Pool& apool) : Methoded(apool) {
1.4 parser 315: set_name(*NEW String(pool(), DOM_CLASS_NAME));
1.2 parser 316:
1.3 parser 317: // ^dom::load[some.xml]
1.2 parser 318: add_native_method("load", Method::CT_DYNAMIC, _load, 1, 1);
1.3 parser 319:
1.13 parser 320: // ^dom.save[options hash;some.xml]
1.8 parser 321: add_native_method("save", Method::CT_DYNAMIC, _save, 2, 2);
1.2 parser 322:
1.13 parser 323: // ^dom.string[options hash] <doc/>
1.7 parser 324: add_native_method("string", Method::CT_DYNAMIC, _string, 1, 1);
1.9 parser 325:
1.13 parser 326: // ^dom.file[options hash] file with "<doc/>"
1.9 parser 327: add_native_method("file", Method::CT_DYNAMIC, _file, 1, 1);
1.10 parser 328:
329: // ^dom.xslt[stylesheet filename]
1.12 parser 330: // ^dom.xslt[stylesheet filename;params hash]
331: add_native_method("xslt", Method::CT_DYNAMIC, _xslt, 1, 2);
1.6 parser 332:
1.2 parser 333: }
334: // global variable
335:
336: Methoded *Dom_class;
337:
338: // creator
339:
340: Methoded *MDom_create(Pool& pool) {
341: // Use the static initializers to initialize the Xalan-C++ and Xerces-C++ platforms.
342: // You must initialize Xerces-C++ once per process
343: XMLPlatformUtils::Initialize();
344: XalanTransformer::initialize();
345:
346: return Dom_class=new(pool) MDom(pool);
347: }
E-mail: