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