如何让lxml输出时保留>而非转义为>以减少Diff噪声?
解决lxml处理Android XML时保留原始实体转义的问题
问题分析
处理Android strings.xml 时,原文件中<string>标签的文本包含&lt;b>这类双重转义的HTML格式内容(实际对应显示<b>)。使用lxml修改name属性添加前缀后,输出文本中的>会被额外转义为&gt;,导致原内容从&lt;b>变成&lt;b&gt;,增加Diff对比的干扰。
解决方案
核心思路是让lxml解析时保留原始实体引用,输出时不额外转义合法的文本字符,具体分两步:
1. 读取XML时禁用实体解析
使用XMLParser设置resolve_entities=False,避免lxml将&解析为&,从而保留原始的实体转义格式:
from lxml import etree # 配置解析器:禁用实体解析,保留原文件空白格式 parser = etree.XMLParser(resolve_entities=False, preserve_whitespace=True) tree = etree.parse("strings.xml", parser) root = tree.getroot()
2. 修改属性并输出XML
为name属性添加前缀后,使用tostring输出时保留原始格式,不额外转义>:
# 为<string>标签的name属性添加前缀 prefix = "app_" for string_node in root.findall("string"): current_name = string_node.get("name") if current_name: string_node.set("name", f"{prefix}{current_name}") # 输出处理后的XML,保留原始转义 output_content = etree.tostring( tree, encoding="utf-8", method="xml", pretty_print=True, xml_declaration=True ) # 写入文件 with open("modified_strings.xml", "wb") as f: f.write(output_content)
备选方案:自定义转义规则
如果需要更精细控制转义字符,可以自定义escape函数,仅转义XML语法要求的<和&,不转义>:
def custom_xml_escape(text): # 只转义XML必须转义的字符:& 和 < text = text.replace("&", "&") text = text.replace("<", "<") # 不转义>,保留原始格式 return text # 输出时指定自定义转义函数 output_content = etree.tostring( tree, encoding="utf-8", method="xml", pretty_print=True, xml_declaration=True, escape=custom_xml_escape )
验证效果
处理后的XML文件中,原有的&lt;b>会被完整保留,不会变成&lt;b&gt;,Diff对比时仅会显示name属性的前缀修改,减少无关干扰。
内容的提问来源于stack exchange,提问作者user2347638
相关产品推荐
相关产品推荐

