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 doc = libxml2dom.macrolib.parseFile(filename) 55 self.stylesheets.append(libxsltmod.xsltParseStylesheetDoc(doc)) 56 57 def __del__(self): 58 59 """ 60 Tidy up the stylesheet documents. 61 """ 62 63 for stylesheet in self.stylesheets: 64 libxsltmod.xsltFreeStylesheet(stylesheet) 65 66 def send_output(self, stream, encoding, document): 67 68 """ 69 Send output to the given 'stream' using the given output encoding for 70 the given 'document'. 71 """ 72 73 result = self.get_result(document) 74 75 if result is not None: 76 stream.write(result.toString(encoding)) 77 else: 78 raise OutputError, "Transformation failed." 79 80 def get_result(self, document): 81 82 """ 83 Return a transformed document produced from the object's stylesheets and 84 the given 'document'. 85 """ 86 87 result = self._get_result(document) 88 89 if result is not None: 90 return libxml2dom.adoptNodes([result])[0] 91 else: 92 raise OutputError, "Transformation failed." 93 94 def _get_result(self, document): 95 96 """ 97 Return a transformation of the given 'document'. 98 """ 99 100 if hasattr(document, "as_native_node"): 101 document = document.as_native_node() 102 103 # Transform the localised instance into the final output. 104 105 parameters = {} 106 for name, reference in self.references.items(): 107 parameters[name.encode("utf-8")] = ("document('%s')" % self._quote(reference)).encode("utf-8") 108 for name, parameter in self.parameters.items(): 109 parameters[name.encode("utf-8")] = ("'%s'" % self._quote(parameter)).encode("utf-8") 110 #print "**", repr(parameters) 111 112 last_result = document 113 for stylesheet in self.stylesheets: 114 result = libxsltmod.xsltApplyStylesheet(stylesheet, last_result, parameters) 115 if last_result is not None: 116 last_result = result 117 else: 118 raise OutputError, "Transformation failed." 119 120 return result 121 122 def _quote(self, s): 123 124 "Make the given parameter string 's' palatable for libxslt." 125 126 return s.replace("'", "%27") 127 128 # vim: tabstop=4 expandtab shiftwidth=4