XSLT as a filter and with parameters

This commit is contained in:
Sam Ruby 2006-10-13 11:01:14 -04:00
parent db79be60cc
commit 21864c3aa8
6 changed files with 106 additions and 12 deletions

View File

@ -32,7 +32,7 @@ from urlparse import urljoin
parser = ConfigParser()
planet_predefined_options = []
planet_predefined_options = ['filters']
def __init__():
"""define the struture of an ini file"""

View File

@ -1,5 +1,19 @@
import os
def quote(string, apos):
""" quote a string so that it can be passed as a parameter """
if type(string) == unicode:
string=string.encode('utf-8')
if apos.startswith("\\"): string.replace('\\','\\\\')
if string.find("'")<0:
return "'" + string + "'"
elif string.find("'")<0:
return '"' + string + '"'
else:
# unclear how to quote strings with both types of quotes for libxslt
return "'" + string.replace("'",apos) + "'"
def run(script, doc, output_file=None, options={}):
""" process an XSLT stylesheet """
@ -12,6 +26,22 @@ def run(script, doc, output_file=None, options={}):
except:
# otherwise, use the command line interface
dom = None
# do it
result = None
if dom:
styledoc = libxml2.parseFile(script)
style = libxslt.parseStylesheetDoc(styledoc)
for key in options.keys():
options[key] = quote(options[key], apos="\xe2\x80\x99")
output = style.applyStylesheet(dom, options)
if output_file:
style.saveResultToFilename(output_file, output, 0)
else:
result = str(output)
style.freeStylesheet()
output.freeDoc()
elif output_file:
import warnings
if hasattr(warnings, 'simplefilter'):
warnings.simplefilter('ignore', RuntimeWarning)
@ -20,16 +50,28 @@ def run(script, doc, output_file=None, options={}):
file.write(doc)
file.close()
# do it
if dom:
styledoc = libxml2.parseFile(script)
style = libxslt.parseStylesheetDoc(styledoc)
result = style.applyStylesheet(dom, None)
style.saveResultToFilename(output_file, result, 0)
style.freeStylesheet()
result.freeDoc()
cmdopts = []
for key,value in options.items():
cmdopts += ['--stringparam', key, quote(value, apos=r"\'")]
os.system('xsltproc %s %s %s > %s' %
(script, ' '.join(cmdopts), docfile, output_file))
os.unlink(docfile)
else:
os.system('xsltproc %s %s > %s' % (script, docfile, output_file))
import sys
from subprocess import Popen, PIPE
options = sum([['--stringparam', key, value]
for key,value in options.items()], [])
proc = Popen(['xsltproc'] + options + [script, '-'],
stdin=PIPE, stdout=PIPE, stderr=PIPE)
result, stderr = proc.communicate(doc)
if stderr:
import planet
planet.logger.error(stderr)
if dom: dom.freeDoc()
if docfile: os.unlink(docfile)
return result

View File

@ -0,0 +1,7 @@
[Planet]
filters = translate.xslt
filter_directories = tests/data/filter
[translate.xslt]
in = aeiou
out = AEIOU

View File

@ -0,0 +1,20 @@
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="in"/>
<xsl:param name="out"/>
<!-- translate $in characters to $out in attribute values -->
<xsl:template match="@*">
<xsl:attribute name="{name()}">
<xsl:value-of select="translate(.,$in,$out)"/>
</xsl:attribute>
</xsl:template>
<!-- pass through everything else -->
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

25
tests/test_filter_xslt.py Normal file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env python
import unittest, xml.dom.minidom
from planet import shell, config, logger
class XsltFilterTests(unittest.TestCase):
def test_xslt_filter(self):
config.load('tests/data/filter/translate.ini')
testfile = 'tests/data/filter/category-one.xml'
input = open(testfile).read()
output = shell.run(config.filters()[0], input, mode="filter")
dom = xml.dom.minidom.parseString(output)
catterm = dom.getElementsByTagName('category')[0].getAttribute('term')
self.assertEqual('OnE', catterm)
try:
import libxslt
except:
try:
from subprocess import Popen, PIPE
except ImportError:
logger.warn("libxslt is not available => can't test xslt filters")
del XsltFilterTests.test_xslt_filter

View File

@ -92,6 +92,6 @@ try:
del FilterTests.test_xpath_filter
except ImportError:
logger.warn("Popen is not available => can't test filters")
logger.warn("Popen is not available => can't test standard filters")
for method in dir(FilterTests):
if method.startswith('test_'): delattr(FilterTests,method)