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