def render(self, header = 1): # start out with the default renderer BlosxomRenderer.render(self, header) pyhttp = self.request.getHttp() useGzip = False if self.config.get('useGzip',False): if pyhttp.has_key('HTTP_ACCEPT_ENCODING'): # encodings = pyhttp['HTTP_ACCEPT_ENCODING'].split(",") # if "gzip" in encodings: if pyhttp['HTTP_ACCEPT_ENCODING'].find("gzip") != -1: useGzip = True self.addHeader("content-encoding","gzip") # if this flavour is not supposed to have XSLT translation run on it # then we just output the buffer as it is. Ideally, this statement # should never be true anymore, but just in case, this is a failsafe if self.data['flavour'] not in self.config.get('xsltFlavours',[]): self._outputBuffer = self._compressBuffer(useGzip) self._out.write('\n'.join(['%s: %s' % (x, self._header[x]) for x in self._header.keys()])) self._out.write('\n\n') self._out.write(self._outputBuffer) return # check to see if the browser is an XSLT browser userAgent = pyhttp['HTTP_USER_AGENT'] flavorREs = self.config.get('xsltBrowsers',[]) # if the browser can render XSLT natively, as indicated by the # xsltBrowsers config option, then we don't need to rerender it for x in flavorREs: matchobj = re.search(x,userAgent) if matchobj: self._outputBuffer = self._compressBuffer(useGzip) self._out.write('\n'.join(['%s: %s' % (x, self._header[x]) for x in self._header.keys()])) self._out.write('\n\n') self._out.write(self._outputBuffer) return # # otherwise do the XSLT transform # # find the sheet # eventually this will also be automated, where it digs in the XML, but # that is not the case now. Instead it looks in the dict from the # configuration file xsltSheetDict = self.config.get('xsltSheets',{}) if xsltSheetDict.has_key(self.data['flavour']): xsltSheet = xsltSheetDict[self.data['flavour']] else: # FIXME: some error processing would go here xsltSheet = "/NOFILEFOUND" xsltEngine = self.config.get('xsltEngine','xsltproc') xsltEngineParams = self.config.get('xsltEngineParams',{}) content = None # try to use libxslt if it's requested if (self.config.get('xsltEngine','') == 'libxslt'): # try: # this is needed to render without shelling out import libxml2 import libxslt doc = libxml2.parseDoc(self._outputBuffer) # this attempts to find the xml-stylesheet tag in the document # if it can find it, then it overwrites the original stylesheet request ss = None rootNode = doc.children while ss == None and rootNode != None: if rootNode.name == 'xml-stylesheet': matchObj = re.match('.*href="([^"]*)"',rootNode.content) if matchObj: ss = matchObj.groups()[0] if self.config.get('serverBase',None): xsltSheet = self.config.get('serverBase','')+os.sep+ss else: rootNode = rootNode.get_next() styledoc = libxml2.parseFile(xsltSheet) style = libxslt.parseStylesheetDoc(styledoc) result = style.applyStylesheet(doc,xsltEngineParams) content = style.saveResultToString(result) # try to figure out the content type based on the XSLT method parameter contentMapping = self.config.get('xsltContentMapping',{}) outputMethod = style.method() if contentMapping.has_key(outputMethod): self.addHeader('Content-type', contentMapping[outputMethod]) else: self.addHeader('Content-type', "text/html") # style.freeStylesheet() # doc.freeDoc() # result.freeDoc() # except: # pass # if xsltproc is requested or the page hasn't been rendered yet, do this if (self.config.get('xsltEngine','') == 'xsltproc' or content == None): # store the output buffer to a temp file tf = tempfile.mktemp(".xml") f = open(tf,"w") f.write(self._outputBuffer) f.close() xsltEngineParamsString = " ".join(["--param %s %s" % (mem, xsltEngineParams[mem]) for mem in xsltEngineParams]) f = open(tempfile.mktemp(".txt"),"w") f.write("""%s %s %s %s""" % (xsltEngine, xsltEngineParamsString, xsltSheet, tf)) f.close() childStdout, childStdin, childStderr = popen2.popen3("""%s %s %s %s""" % (xsltEngine, xsltEngineParamsString, xsltSheet, tf)) childStdin.close() content = "" while 1: line = childStdout.readline() if not line: break content = content + line # os.unlink(tf) childStdout.close() childStderr.close() self.addHeader('Content-type', 'text/html') # in theory this should also be validated too...it's conceivable that # there might be different output methods than just text/html, for # instance, someone may do a transform to SVG for a certain flavour self._outputBuffer = content.decode('utf-8') self._outputBuffer = self._compressBuffer(useGzip) self._out.write('\n'.join(['%s: %s' % (x, self._header[x]) for x in self._header.keys()])) self._out.write('\n\n') self._out.write(self._outputBuffer)
def __init__(self, request, stdoutput = sys.stdout): BlosxomRenderer.__init__(self, request, stdoutput) self.request = request self.data = self.request.getData() self.config = self.request.getConfiguration() self._outputBuffer = ""