1 #!/usr/bin/env python 2 3 """ 4 XSL output classes and functions. 5 6 Copyright (C) 2005 Paul Boddie <paul@boddie.org.uk> 7 8 This library is free software; you can redistribute it and/or 9 modify it under the terms of the GNU Lesser General Public 10 License as published by the Free Software Foundation; either 11 version 2.1 of the License, or (at your option) any later version. 12 13 This library is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 Lesser General Public License for more details. 17 18 You should have received a copy of the GNU Lesser General Public 19 License along with this library; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 """ 22 23 __version__ = "0.1" 24 25 # NOTE: Make this use other implementations, too. 26 27 import libxsltmod 28 import libxml2dom 29 30 class OutputError(Exception): 31 pass 32 33 class Processor: 34 35 """ 36 A handler which can prepare output for an XMLTools2 template. 37 """ 38 39 def __init__(self, filenames, references=None, parameters=None): 40 41 """ 42 Initialise the handler with the 'filenames' of stylesheets producing the 43 final output, a 'references' dictionary indicating related stylesheets. 44 Additional 'parameters' may also be specified as a dictionary. 45 """ 46 47 self.references = references or {} 48 self.parameters = parameters or {} 49 50 # Remember the stylesheet documents. 51 52 self.stylesheets = [] 53 for filename in filenames: 54 self.stylesheets.append(libxsltmod.xsltParseStylesheetFile(filename)) 55 56 def __del__(self): 57 58 """ 59 Tidy up the stylesheet documents. 60 """ 61 62 for stylesheet in self.stylesheets: 63 libxsltmod.xsltFreeStylesheet(stylesheet) 64 65 def send_output(self, stream, encoding, document): 66 67 """ 68 Send output to the given 'stream' using the given output encoding for 69 the given 'document'. 70 """ 71 72 result = self.get_result(document) 73 74 if result is not None: 75 stream.write(result.toString(encoding)) 76 else: 77 raise OutputError, "Transformation failed." 78 79 def get_result(self, document): 80 81 """ 82 Return a transformed document produced from the object's stylesheets and 83 the given 'document'. 84 """ 85 86 result = self._get_result(document) 87 88 if result is not None: 89 return libxml2dom.adoptNodes([result])[0] 90 else: 91 raise OutputError, "Transformation failed." 92 93 def _get_result(self, document): 94 95 """ 96 Return a transformation of the given 'document'. 97 """ 98 99 if hasattr(document, "as_native_node"): 100 document = document.as_native_node() 101 102 # Transform the localised instance into the final output. 103 104 parameters = {} 105 for name, reference in self.references.items(): 106 parameters[name.encode("utf-8")] = ("document('%s')" % self._quote(reference)).encode("utf-8") 107 for name, parameter in self.parameters.items(): 108 parameters[name.encode("utf-8")] = ("'%s'" % self._quote(parameter)).encode("utf-8") 109 #print "**", repr(parameters) 110 111 last_result = document 112 for stylesheet in self.stylesheets: 113 result = libxsltmod.xsltApplyStylesheet(stylesheet, last_result, parameters) 114 if last_result is not None: 115 last_result = result 116 else: 117 raise OutputError, "Transformation failed." 118 119 return result 120 121 def _quote(self, s): 122 123 "Make the given parameter string 's' palatable for libxslt." 124 125 return s.replace("'", "%27") 126 127 # vim: tabstop=4 expandtab shiftwidth=4