summaryrefslogtreecommitdiff
path: root/repoze/bfg/xslt.py
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2008-09-26 06:42:53 +0000
committerChris McDonough <chrism@agendaless.com>2008-09-26 06:42:53 +0000
commit01a6e567a20096f6033cc603667f4e900d2a44c3 (patch)
treea87431383a63dbafbb5cccdfa7679b9187bdfc29 /repoze/bfg/xslt.py
parent26216e5526ca56d886d2348f9e1f09b86622aa72 (diff)
downloadpyramid-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.py85
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