如何使用lxml XSLT解码XML文档中的西里尔文属性值?
解决lxml XSLT转换后西里尔文属性转Unicode转义序列的问题
问题场景
使用lxml执行XSLT转换XML时,属性中的西里尔文被自动转为&#xXXXX;格式的Unicode转义序列,即使设置encoding='unicode'也无法保留原始字符,需要输出保留原始西里尔文属性值的XML结果。
原代码
import lxml.etree as ET data = '<Response> <ОргМн Наим="ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ"> <Орг НаимЮЛПолн="НАИМЕНОВАНИЕ 5087"> <ГРНДата ГРН="5087" ДатаЗаписи="2008-11-18"/> </Орг> </ОргМн> </Response>' rools = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:copy-of select="*" /> </xsl:template> </xsl:stylesheet>' root = ET.fromstring(data) xslt = ET.fromstring(rools) transform = ET.XSLT(xslt) newdom = transform(root) result = ET.tostring(newdom, encoding='unicode') print(result)
解决方法
需要从两个方面调整:
- 在XSLT样式表中添加输出声明,明确指定编码和输出格式
- 调整
ET.tostring的序列化参数,避免对非ASCII字符进行实体转义
修改后的代码如下:
import lxml.etree as ET data = '<Response> <ОргМн Наим="ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ"> <Орг НаимЮЛПолн="НАИМЕНОВАНИЕ 5087"> <ГРНДата ГРН="5087" ДатаЗаписи="2008-11-18"/> </Орг> </ОргМн> </Response>' # 新增xsl:output声明,指定UTF-8编码和XML输出方法 rools = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output encoding="UTF-8" method="xml" indent="yes"/> <xsl:template match="/"> <xsl:copy-of select="*" /> </xsl:template> </xsl:stylesheet>' root = ET.fromstring(data) xslt = ET.fromstring(rools) transform = ET.XSLT(xslt) newdom = transform(root) # 使用utf-8编码序列化后解码为Unicode,同时保留缩进 result = ET.tostring(newdom, encoding='utf-8', pretty_print=True).decode('utf-8') print(result)
说明
- XSLT中的
<xsl:output encoding="UTF-8" method="xml" indent="yes"/>明确告诉处理器输出UTF-8编码的XML,并且格式化缩进 ET.tostring指定encoding='utf-8'序列化后,再用decode('utf-8')转为字符串,这样非ASCII的西里尔文会直接保留,不会被转成实体序列- 若需要更精细的控制,可以使用
lxml.etree.XMLSerializer类,自定义序列化规则
输出结果
<Response> <ОргМн Наим="ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ"> <Орг НаимЮЛПолн="НАИМЕНОВАНИЕ 5087"> <ГРНДата ГРН="5087" ДатаЗаписи="2008-11-18"/> </Орг> </ОргМн> </Response>
内容的提问来源于stack exchange,提问作者losob22630
相关产品推荐
相关产品推荐

