def transform(self, indata, config=None, parameters={}): strparams = {} if config: # paths to be used with the document() function # must use unix path separators if os.sep == "\\": config = config.replace(os.sep, "/") # print("Tranform: Using config %s. Contents:" % config) # print(util.readfile(config)) config_fullpath = os.path.abspath(config) strparams['configurationfile'] = XSLT.strparam(config_fullpath) removefiles = [] for key, value in parameters.items(): if key.endswith("file") and value: if all(ord(c) < 128 and c != " " for c in value): # IF the file name contains ONLY ascii chars and # no spaces, we can use it directly. However, we # need to relativize path of file relative to the # XSL file we'll be using. The mechanism could be # clearer... value = os.path.relpath(value, self.templdir) else: # If the filename contains non-ascii characters or # space, any attempt to eg # "document($annotationfile)" in the XSLT document # will silently fail. Seriously, f**k lxml's error # handling. In this case, copy it to a temp file # (in the temporary templdir, with ascii filename) # and use that. contents = util.readfile(value) value = os.path.basename(value) value = "".join(c for c in value if ord(c) < 128 and c != " ") removefiles.append(self.templdir + os.sep + value) util.writefile(self.templdir + os.sep + value, contents) if os.sep == "\\": value = value.replace(os.sep, "/") strparams[key] = XSLT.strparam(value) try: return self._transformer(indata, **strparams) except etree.XSLTApplyError as e: # the exception will only contain the last error. Errors # emanting from the xhtml file will not have file/line # number information. Errors emanting from the xslt file # do have file/line number info, and is probably more # useful to deal with. for error in self._transformer.error_log: if error.line: log.error("%s: %s (line %s)" % (error.filename, error.message, error.line)) raise errors.TransformError(str(e)) finally: for f in removefiles: util.robust_remove(f) # FIXME: This can never be reached, if _transformer() does not # raise an error, the above returns immediately. if len(self._transformer.error_log) > 0: raise errors.TransformError(str(_transformer.error_log))
def transform(self, indata, config=None, parameters={}): strparams = {} if config: # paths to be used with the document() function # must use unix path separators if os.sep == "\\": config = config.replace(os.sep, "/") # print("Tranform: Using config %s. Contents:" % config) # print(util.readfile(config)) config_fullpath = os.path.abspath(config) strparams['configurationfile'] = XSLT.strparam(config_fullpath) removefiles = [] for key, value in parameters.items(): if key.endswith("file") and value: if all(ord(c) < 128 and c != " " for c in value): # IF the file name contains ONLY ascii chars and # no spaces, we can use it directly. However, we # need to relativize path of file relative to the # XSL file we'll be using. The mechanism could be # clearer... value = os.path.relpath(value, self.templdir) else: # If the filename contains non-ascii characters or # space, any attempt to eg # "document($annotationfile)" in the XSLT document # will silently fail. Seriously, f**k lxml's error # handling. In this case, copy it to a temp file # (in the temporary templdir, with ascii filename) # and use that. contents = util.readfile(value) value = os.path.basename(value) value = "".join(c for c in value if ord(c) < 128 and c != " ") removefiles.append(self.templdir+os.sep+value) util.writefile(self.templdir+os.sep+value, contents) if os.sep == "\\": value = value.replace(os.sep, "/") strparams[key] = XSLT.strparam(value) try: return self._transformer(indata, **strparams) except etree.XSLTApplyError as e: # the exception will only contain the last error. Errors # emanting from the xhtml file will not have file/line # number information. Errors emanting from the xslt file # do have file/line number info, and is probably more # useful to deal with. for error in self._transformer.error_log: if error.line: log.error("%s: %s (line %s)" % (error.filename, error.message, error.line)) raise errors.TransformError(str(e)) finally: for f in removefiles: util.robust_remove(f) # FIXME: This can never be reached, if _transformer() does not # raise an error, the above returns immediately. if len(self._transformer.error_log) > 0: raise errors.TransformError(str(_transformer.error_log))
def parse_formex(self, doc, source): parser = etree.XMLParser(remove_blank_text=True) sourcetree = etree.parse(source, parser).getroot() fp = self.resourceloader.openfp("xsl/formex.xsl") xslttree = etree.parse(fp, parser) transformer = etree.XSLT(xslttree) params = etree.XSLT resulttree = transformer(sourcetree, about=XSLT.strparam(doc.uri), rdftype=XSLT.strparam(str(doc.meta.value(URIRef(doc.uri), RDF.type)))) return resulttree # re-parse to fix whitespace buffer = BytesIO(etree.tostring(resulttree, encoding="utf-8")) return etree.parse(buffer, parser)
def create_report_templates(self, config): """ This object takes the full configuration element and the path to an XSLT and does the transforms necessary to create templates for use in BARD reporting """ xslt_path = settings.BARD_TRANSFORM template_dir = '%s/django/publicmapping/redistricting/templates' % config.xpath('//Project')[0].get('root') # Open up the XSLT file and create a transform f = file(xslt_path) xml = parse(f) transform = XSLT(xml) # For each legislative body, create the reporting step HTML # template. If there is no config for a body, the XSLT transform # should create a "Sorry, no reports" template bodies = config.xpath('//DistrictBuilder/LegislativeBodies/LegislativeBody') for body in bodies: # Name the template after the body's name body_id = body.get('id') body_name = body.get('name')[:256] logging.info("Creating BARD reporting template for %s", body_name) body_name = body_name.lower() template_path = '%s/bard_%s.html' % (template_dir, body_name) # Pass the body's identifier in as a parameter xslt_param = XSLT.strparam(body_id) result = transform(config, legislativebody = xslt_param) f = open(template_path, 'w') f.write(str(result)) f.close()
def transform(self, indata, config=None, parameters={}): strparams = {} if config: # paths to be used with the document() function # must use unix path separators if os.sep == "\\": config = config.replace(os.sep, "/") strparams['configurationfile'] = XSLT.strparam(config) for key, value in parameters.items(): if key.endswith("file"): # relativize path of file relative to the XSL file # we'll be using. The mechanism could be clearer... value = os.path.relpath(value, self.templdir) if os.sep == "\\": value = value.replace(os.sep, "/") strparams[key] = XSLT.strparam(value) try: return self._transformer(indata, **strparams) except etree.XSLTApplyError as e: raise errors.TransformError(str(e)) if len(self._transformer.error_log) > 0: raise errors.TransformError(str(_transformer.error_log))
def create_report_templates(self, config): """ This object takes the full configuration element and the path to an XSLT and does the transforms necessary to create templates for use in BARD reporting """ xslt_path = settings.BARD_TRANSFORM template_dir = '%s/django/publicmapping/redistricting/templates' % config.xpath( '//Project')[0].get('root') # Open up the XSLT file and create a transform f = file(xslt_path) xml = parse(f) transform = XSLT(xml) # For each legislative body, create the reporting step HTML # template. If there is no config for a body, the XSLT transform # should create a "Sorry, no reports" template bodies = config.xpath( '//DistrictBuilder/LegislativeBodies/LegislativeBody') for body in bodies: # Name the template after the body's name body_id = body.get('id') body_name = body.get('name')[:256] logger.info("Creating BARD reporting template for %s", body_name) body_name = body_name.lower() template_path = '%s/bard_%s.html' % (template_dir, body_name) # Pass the body's identifier in as a parameter xslt_param = XSLT.strparam(body_id) result = transform(config, legislativebody=xslt_param) f = open(template_path, 'w') f.write(str(result)) f.close()