diff options
| author | Chris McDonough <chrism@agendaless.com> | 2008-09-26 06:42:53 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2008-09-26 06:42:53 +0000 |
| commit | 01a6e567a20096f6033cc603667f4e900d2a44c3 (patch) | |
| tree | a87431383a63dbafbb5cccdfa7679b9187bdfc29 /repoze/bfg/xslt.py | |
| parent | 26216e5526ca56d886d2348f9e1f09b86622aa72 (diff) | |
| download | pyramid-01a6e567a20096f6033cc603667f4e900d2a44c3.tar.gz pyramid-01a6e567a20096f6033cc603667f4e900d2a44c3.tar.bz2 pyramid-01a6e567a20096f6033cc603667f4e900d2a44c3.zip | |
Move to Chameleon.
Diffstat (limited to 'repoze/bfg/xslt.py')
| -rw-r--r-- | repoze/bfg/xslt.py | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/repoze/bfg/xslt.py b/repoze/bfg/xslt.py new file mode 100644 index 000000000..949bde6da --- /dev/null +++ b/repoze/bfg/xslt.py @@ -0,0 +1,85 @@ +import os + +from webob import Response + +from zope.component import queryUtility +from zope.component import getSiteManager +from zope.component.interfaces import ComponentLookupError + +from zope.interface import classProvides +from zope.interface import implements + +from repoze.bfg.path import caller_path + +from repoze.bfg.interfaces import INodeTemplate +from repoze.bfg.interfaces import ITemplateFactory + +def get_transform(path, node): + """ Return a callable transform object. When called, the + transform will return a string. The ``path`` argument should be a + package-relative path (also may be absolute) to an XSLT file. + When called, the transform will use the kwargs in ``*kw`` as top + level names and the lxml node at ``node``.""" + # Render using XSLT + path = caller_path(path) + + template = queryUtility(INodeTemplate, path) + if template is None: + if not os.path.exists(path): + raise ValueError('Missing template file: %s' % path) + template = XSLTemplateFactory(path) + try: + sm = getSiteManager() + except ComponentLookupError: + pass + else: + sm.registerUtility(template, INodeTemplate, name=path) + return template + +def render_transform(path, node, **kw): + """ Render a XSL template at the package-relative path (may also + be absolute) using the kwargs in ``*kw`` as top-level names and + the lxml node at ``node`` and return a string.""" + path = caller_path(path) + template = get_transform(path, node) + return template(node, **kw) + +def render_transform_to_response(path, node, **kw): + """ Render a XSL template at the package-relative path (may also + be absolute) using the kwargs in ``*kw`` as top-level names and + the lxml node at ``node`` and return a Response object.""" + path = caller_path(path) + result = render_transform(path, node, **kw) + return Response(result) + +class XSLTemplateFactory(object): + classProvides(ITemplateFactory) + implements(INodeTemplate) + + def __init__(self, path, auto_reload=False): + self.path = path + self.auto_reload = auto_reload + + def __call__(self, node, **kw): + processor = get_processor(self.path, self.auto_reload) + result = str(processor(node, **kw)) + return result + +# Manage XSLT processors on a per-thread basis +import threading +from lxml import etree +xslt_pool = threading.local() +def get_processor(xslt_fn, auto_reload=False): + if not auto_reload: + try: + return xslt_pool.processors[xslt_fn] + except AttributeError: + xslt_pool.processors = {} + except KeyError: + pass + + # Make a processor and add it to the pool + source = etree.ElementTree(file=xslt_fn) + proc = etree.XSLT(source) + xslt_pool.processors[xslt_fn] = proc + return proc |
