diff --git a/planet/config.py b/planet/config.py index cd6a997..99d3cda 100644 --- a/planet/config.py +++ b/planet/config.py @@ -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""" diff --git a/planet/shell/xslt.py b/planet/shell/xslt.py index 593f7b9..ecdd673 100644 --- a/planet/shell/xslt.py +++ b/planet/shell/xslt.py @@ -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 diff --git a/tests/data/filter/translate.ini b/tests/data/filter/translate.ini new file mode 100644 index 0000000..0d34e74 --- /dev/null +++ b/tests/data/filter/translate.ini @@ -0,0 +1,7 @@ +[Planet] +filters = translate.xslt +filter_directories = tests/data/filter + +[translate.xslt] +in = aeiou +out = AEIOU diff --git a/tests/data/filter/translate.xslt b/tests/data/filter/translate.xslt new file mode 100644 index 0000000..25968d7 --- /dev/null +++ b/tests/data/filter/translate.xslt @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_filter_xslt.py b/tests/test_filter_xslt.py new file mode 100644 index 0000000..ca7994e --- /dev/null +++ b/tests/test_filter_xslt.py @@ -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 diff --git a/tests/test_filters.py b/tests/test_filters.py index e8c5633..aac71f2 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -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)