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