Back to index

moin  1.9.0~rc2
text_xslt.py
Go to the documentation of this file.
00001 # -*- coding: iso-8859-1 -*-
00002 """
00003     MoinMoin - XML Parser
00004 
00005     This parser was tested with 4Suite 1.0a4 and 1.0b1.
00006 
00007     What's new:
00008     * much cleaner code
00009     * stylesheet can be extended to support other format:
00010         e.g. Docbook parser using docbook->html .xsl stylesheet
00011 
00012     @copyright: 2001-2003 Juergen Hermann <jh@web.de>,
00013                 2005 Henry Ho <henryho167@hotmail.com>,
00014                 2005 by MoinMoin:AlexanderSchremmer
00015     @license: GNU GPL, see COPYING for details.
00016 """
00017 
00018 # cStringIO cannot be used because it doesn't handle Unicode.
00019 import StringIO
00020 
00021 from MoinMoin import caching, config, wikiutil, Page
00022 
00023 Dependencies = []
00024 
00025 class Parser:
00026     """ Send XML file formatted via XSLT. """
00027     caching = 1
00028     Dependencies = Dependencies
00029 
00030     def __init__(self, raw, request, **kw):
00031         self.raw = raw
00032         self.request = request
00033         self.form = request.form
00034         self._ = request.getText
00035         self.base_scheme = 'wiki'
00036         self.base_uri = 'wiki://Self/'
00037         self.key = 'xslt'
00038 
00039     def format(self, formatter):
00040         """ Send the text. """
00041         _ = self._
00042 
00043         if not self.request.cfg.allow_xslt:
00044             # use plain text parser if XSLT is not allowed
00045             # can be activated in wikiconfig.py
00046             from MoinMoin.parser.text import Parser as TextParser
00047             self.request.write(formatter.sysmsg(1) +
00048                                formatter.rawHTML(_('XSLT option disabled, please look at HelpOnConfiguration.', wiki=True)) +
00049                                formatter.sysmsg(0))
00050             TextParser(self.raw, self.request).format(formatter)
00051             return
00052 
00053         try:
00054             # try importing Ft from 4suite
00055             # if import fails or its version is not 1.x, error msg
00056             from Ft.Xml import __version__ as ft_version
00057             assert ft_version.startswith('1.')
00058         except (ImportError, AssertionError):
00059             self.request.write(self.request.formatter.sysmsg(1) +
00060                                self.request.formatter.text(_('XSLT processing is not available, please install 4suite 1.x.')) +
00061                                self.request.formatter.sysmsg(0))
00062         else:
00063             from Ft.Lib import Uri
00064             from Ft.Xml import InputSource
00065             from Ft.Xml.Xslt.Processor import Processor
00066             from Ft import FtException
00067 
00068             msg = None
00069 
00070             try:
00071                 # location of SchemeRegisteryResolver has changed since 1.0a4
00072                 if ft_version >= "1.0a4" or ft_version == "1.0" or ("1.0.1" <= ft_version <= "1.0.9"):
00073                     # such version numbers suck!
00074                     import Ft.Lib.Resolvers # Do not remove! it looks unused, but breaks when removed!!!
00075 
00076                 class MoinResolver(Uri.SchemeRegistryResolver):
00077                     """ supports resolving self.base_uri for actual pages in MoinMoin """
00078                     def __init__(self, handlers, base_scheme):
00079                         Uri.SchemeRegistryResolver.__init__(self, handlers)
00080                         self.supportedSchemes.append(base_scheme)
00081 
00082                 # setting up vars for xslt Processor
00083                 out_file = StringIO.StringIO()
00084                 wiki_resolver = MoinResolver(
00085                                     handlers={self.base_scheme: self._resolve_page, },
00086                                     base_scheme=self.base_scheme)
00087                 input_factory = InputSource.InputSourceFactory(resolver=wiki_resolver)
00088 
00089                 page_uri = self.base_uri + wikiutil.url_quote(formatter.page.page_name)
00090                 # 4Suite needs an utf-8 encoded byte string instead of an unicode object
00091                 raw = self.raw.strip().encode('utf-8')
00092                 self.processor = Processor()
00093                 self.append_stylesheet() # hook, for extending this parser
00094                 self.processor.run(
00095                     input_factory.fromString(raw, uri=page_uri),
00096                     outputStream=out_file)
00097                 # Convert utf-8 encoded byte string into unicode
00098                 result = out_file.getvalue().decode('utf-8')
00099                 result = self.parse_result(result) # hook, for extending this parser
00100 
00101             except FtException, msg:
00102                 etype = "XSLT"
00103             except Uri.UriException, msg:
00104                 etype = "XSLT"
00105             except IOError, msg:
00106                 etype = "I/O"
00107 
00108             if msg:
00109                 text = wikiutil.escape(self.raw)
00110                 text = text.expandtabs()
00111                 text = text.replace('\n', '<br>\n')
00112                 text = text.replace(' ', '&nbsp;')
00113                 before = _('%(errortype)s processing error') % {'errortype': etype, }
00114                 title = u"<strong>%s: %s</strong><p>" % (before, msg)
00115                 self.request.write(title)
00116                 self.request.write(text.decode(config.charset))
00117             else:
00118                 self.request.write(result)
00119                 cache = caching.CacheEntry(self.request, formatter.page, self.key, scope='item')
00120                 cache.update(result)
00121 
00122     def _resolve_page(self, uri, base):
00123         """ URI will be resolved into StringIO with actual page content """
00124         from Ft.Lib import Uri
00125         base_uri = self.base_uri
00126 
00127         if uri.startswith(base_uri):
00128             pagename = uri[len(base_uri):]
00129             page = Page.Page(self.request, pagename)
00130             if page.exists():
00131                 result = StringIO.StringIO(page.getPageText().encode(config.charset))
00132             else:
00133                 raise Uri.UriException(Uri.UriException.RESOURCE_ERROR, loc=uri,
00134                                        msg='Page does not exist')
00135         else:
00136             result = Uri.UriResolverBase.resolve(self, uri, base)
00137 
00138         return result
00139 
00140     def append_stylesheet(self):
00141         """ for other parsers based on xslt (i.e. docbook-xml) """
00142         pass
00143 
00144     def parse_result(self, result):
00145         """ additional parsing to the resulting XSLT'ed result before saving """
00146         return result
00147