XML解析时如何传入两种编码类型作为参数实现统一解析
问题根因
当前代码中ET.tostring(..., encoding='utf-8/UTF-16', ...)写法错误,encoding参数仅支持传入单个合法编码字符串,斜杠拼接多编码的写法会直接触发编码识别异常。xml.etree.ElementTree的parse方法本身遵循XML标准规范,会自动读取XML文件头部<?xml version="1.0" encoding="xxx"?>的编码声明,原生支持自动识别UTF-8、UTF-16两种编码的输入文件,无需提前硬编码指定输入编码。
正确实现
最简适配方案(覆盖99%常规场景)
统一将解析后的XML结构输出为单一编码(推荐兼容性最好的UTF-8)交给xmltodict处理即可,无论输入文件是UTF-8还是UTF-16都能正常适配:
import xml.etree.ElementTree as ET import xmltodict def parse_xml(xml_file_path): # 自动识别输入文件编码,兼容UTF-8/UTF-16 tree = ET.parse(xml_file_path) xml_root = tree.getroot() # 统一输出为UTF-8编码,禁止传入多编码拼接值 xml_bytes = ET.tostring(xml_root, encoding='utf-8', method='xml') # 转换为字典返回 return dict(xmltodict.parse(xml_bytes))
兜底兼容方案(应对无编码声明的异常XML)
如果遇到部分缺失头部编码声明、自动识别失败的XML文件,可以通过判断文件BOM头手动识别编码:UTF-16编码的文件开头固定带0xff 0xfe或0xfe 0xff的BOM标识,无BOM的XML默认按UTF-8处理:
import xml.etree.ElementTree as ET import xmltodict def parse_xml(xml_file_path): # 读取二进制内容做编码检测 with open(xml_file_path, 'rb') as f: raw_content = f.read() # 根据BOM判断编码 if raw_content.startswith(b'\xff\xfe') or raw_content.startswith(b'\xfe\xff'): input_encoding = 'utf-16' else: input_encoding = 'utf-8' # 按检测到的编码解析内容 xml_root = ET.fromstring(raw_content.decode(input_encoding)) # 统一转UTF-8后做字典转换 xml_bytes = ET.tostring(xml_root, encoding='utf-8', method='xml') return dict(xmltodict.parse(xml_bytes))
注意:后续处理流程统一固定使用UTF-8即可,不需要保留原文件的UTF-16编码,避免额外增加多编码判断逻辑。
内容的提问来源于stack exchange,提问作者Nikita
相关产品推荐
相关产品推荐

