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