基于lxml的Python XSLT转换失败:制表符分隔文件生成问题
解决lxml XSLT转换TSV文件时的编码与NoneType错误
首先咱们拆解下你遇到的问题:HTML转换正常但TSV失败,核心原因是XSLT输出纯文本(TSV)和HTML/XML的处理逻辑在lxml里完全不同,你的代码用了处理XML节点树的方式来处理纯文本输出,才导致了一系列报错。
为什么会报错?
- AttributeError: 'NoneType' object has no attribute 'decode':当XSLT设置为输出纯文本(
method="text")时,transform(xml_file)返回的_XSLTResultTree对象,用et.tostring()处理会返回None——因为tostring()是专门用来序列化XML/HTML节点的,纯文本输出没有节点结构,它没法生成有效字节流,自然返回None,调用.decode()就会触发错误。 - UnicodeEncodeError:直接用
str(transformed)时,Python会默认使用系统编码(比如Windows上的GBK)去编码Unicode字符串,如果翻译文本里包含UTF-8专属字符(比如中文、特殊符号),就会出现编码失败的问题。
解决方案
第一步:确保TSV的XSLT正确设置输出格式
先检查你的XSLT文件开头是否正确声明了纯文本输出,这是基础前提:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 关键配置:指定输出为纯文本,编码UTF-8 --> <xsl:output method="text" encoding="UTF-8" indent="no"/> <!-- 你的转换逻辑示例 --> <xsl:template match="/TS"> <!-- 输出TSV表头,用制表符分隔 --> <xsl:text>Source Translation Translator Comment </xsl:text> <xsl:for-each select="context/message"> <xsl:value-of select="source"/><xsl:text> </xsl:text> <xsl:value-of select="translation"/><xsl:text> </xsl:text> <xsl:value-of select="translatorcomment"/><xsl:text> </xsl:text> </xsl:for-each> </xsl:template> </xsl:stylesheet>
注意用 表示换行, 表示制表符,确保输出严格符合TSV格式。
第二步:修改Python代码适配纯文本输出
放弃用et.tostring(),改用_XSLTResultTree原生的write()方法,或者直接获取Unicode字符串后指定编码写入:
方法1:用write()直接写入(推荐)
这个方法最可靠,直接利用lxml的输出逻辑,指定编码即可:
import lxml.etree as et xml_file = et.parse(input_xml) xslt_file = et.parse(transform_xsl) transform = et.XSLT(xslt_file) transformed = transform(xml_file) # 二进制模式打开文件,指定UTF-8编码写入 with open(self.output, "wb") as out_file: transformed.write(out_file, encoding="utf-8")
方法2:获取Unicode字符串后写入
如果需要先处理文本内容,可以先转成Unicode字符串,再用文本模式打开文件并指定编码:
import lxml.etree as et xml_file = et.parse(input_xml) xslt_file = et.parse(transform_xsl) transform = et.XSLT(xslt_file) transformed = transform(xml_file) # 获取纯文本内容(Unicode字符串) result_text = str(transformed) # 文本模式打开,指定UTF-8编码写入 with open(self.output, "w", encoding="utf-8") as out_file: out_file.write(result_text)
为什么HTML转换正常?
因为HTML的XSLT输出是标准的XML/HTML节点树,et.tostring()可以正确序列化这个节点树为字节流,所以.decode("utf-8")能正常工作。而TSV是纯文本,没有节点结构,完全不适用这个处理方式。
内容的提问来源于stack exchange,提问作者user707779
相关产品推荐
相关产品推荐

