1 #!/usr/bin/env python 2 3 """ 4 XSL output classes and functions. 5 """ 6 7 # NOTE: Make this use other implementations, too. 8 9 import libxsltmod 10 import libxml2dom 11 12 class OutputError(Exception): 13 pass 14 15 class Processor: 16 17 """ 18 A handler which can prepare output for an XMLTools2 template. 19 """ 20 21 def __init__(self, filenames, references=None, parameters=None): 22 23 """ 24 Initialise the handler with the 'filenames' of stylesheets producing the 25 final output, a 'references' dictionary indicating related stylesheets. 26 Additional 'parameters' may also be specified as a dictionary. 27 """ 28 29 self.references = references or {} 30 self.parameters = parameters or {} 31 32 # Remember the stylesheet documents. 33 34 self.stylesheets = [] 35 for filename in filenames: 36 self.stylesheets.append(libxsltmod.xsltParseStylesheetFile(filename)) 37 38 def __del__(self): 39 40 """ 41 Tidy up the stylesheet documents. 42 """ 43 44 for stylesheet in self.stylesheets: 45 libxsltmod.xsltFreeStylesheet(stylesheet) 46 47 def send_output(self, stream, encoding, document): 48 49 """ 50 Send output to the given 'stream' using the given output encoding for 51 the given 'document'. 52 """ 53 54 result = self.get_result(document) 55 56 if result is not None: 57 stream.write(result.toString(encoding)) 58 else: 59 raise OutputError, "Transformation failed." 60 61 def get_result(self, document): 62 63 """ 64 Return a transformed document produced from the object's stylesheets and 65 the given 'document'. 66 """ 67 68 result = self._get_result(document) 69 70 if result is not None: 71 return libxml2dom.adoptNodes([result])[0] 72 else: 73 raise OutputError, "Transformation failed." 74 75 def _get_result(self, document): 76 77 """ 78 Return a transformation of the given 'document'. 79 """ 80 81 if hasattr(document, "as_native_node"): 82 document = document.as_native_node() 83 84 # Transform the localised instance into the final output. 85 86 parameters = {} 87 for name, reference in self.references.items(): 88 parameters[name.encode("utf-8")] = ("document('%s')" % self._quote(reference)).encode("utf-8") 89 for name, parameter in self.parameters.items(): 90 parameters[name.encode("utf-8")] = ("'%s'" % self._quote(parameter)).encode("utf-8") 91 92 last_result = document 93 for stylesheet in self.stylesheets: 94 result = libxsltmod.xsltApplyStylesheet(stylesheet, last_result, parameters) 95 if last_result is not None: 96 last_result = result 97 else: 98 raise OutputError, "Transformation failed." 99 100 return result 101 102 def _quote(self, s): 103 104 "Make the given parameter string 's' palatable for libxslt." 105 106 return s.replace("'", "%27") 107 108 # vim: tabstop=4 expandtab shiftwidth=4