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 libxslt 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(libxslt.parseStylesheetFile(filename)) 37 38 def __del__(self): 39 40 """ 41 Tidy up the stylesheet documents. 42 """ 43 44 for stylesheet in self.stylesheets: 45 stylesheet.freeStylesheet() 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 # Since result is a native node, use the serialize method. 58 stream.write(result.serialize(encoding)) 59 result.freeDoc() 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.Node(result) 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 94 last_result = document 95 for stylesheet in self.stylesheets: 96 result = stylesheet.applyStylesheet(last_result, parameters) 97 if last_result is not None: 98 if last_result is not document: 99 last_result.freeDoc() 100 last_result = result 101 else: 102 raise OutputError, "Transformation failed." 103 104 return result 105 106 def _quote(self, s): 107 108 "Make the given parameter string 's' palatable for libxslt." 109 110 return s.replace("'", "%27") 111 112 # vim: tabstop=4 expandtab shiftwidth=4