使用ET.fromstring解析XML遇ParseError及遍历终止问题求助
解决XML解析PackageReference的两个问题
一、处理xml.etree.ElementTree.ParseError: not well-formed (invalid token)
即便你确认XML格式合规,也可能存在以下隐藏问题,逐一排查:
- 编码问题:如果XML字符串包含UTF-8 BOM(字节顺序标记),
ET.fromstring无法识别,可先去除:import codecs xml = xml.lstrip(codecs.BOM_UTF8.decode('utf-8')) - 未转义特殊字符:XML中
&、<、>必须转义为&、<、>,检查字符串中是否有未处理的这类字符(比如注释或属性值里的特殊符号)。 - 不可见控制字符:ASCII控制字符(如\x00-\x1F除换行、制表符)会导致解析失败,用正则过滤:
import re xml = re.sub(r'[\x00-\x08\x0B\x0C\x0E-\x1F]', '', xml)
二、解决tree.findall('.//PackageReference')导致程序终止
最常见的原因是XML命名空间未处理,.NET的csproj文件默认带命名空间(如http://schemas.microsoft.com/developer/msbuild/2003),直接用本地名称查找会失败,甚至因未捕获异常导致崩溃,处理方式如下:
- 指定命名空间查找:
import xml.etree.ElementTree as ET root = ET.fromstring(xml) # 提取根元素的命名空间 ns = {'msbuild': root.attrib['xmlns']} # 带命名空间前缀查找元素 package_refs = root.findall('.//msbuild:PackageReference', namespaces=ns) - 捕获异常定位崩溃原因:程序终止大概率是未捕获异常,包裹代码查看具体错误:
try: package_refs = root.findall('.//PackageReference') # 后续处理逻辑 except Exception as e: print(f"崩溃原因:{str(e)}") - 验证XML结构:确认
PackageReference元素的层级是否正确(比如是否嵌套在ItemGroup下),可先打印XML结构:ET.dump(root)
完整示例代码
import xml.etree.ElementTree as ET import codecs import re def parse_package_references(xml_str): # 预处理XML:去除BOM和控制字符 xml_str = xml_str.lstrip(codecs.BOM_UTF8.decode('utf-8')) xml_str = re.sub(r'[\x00-\x08\x0B\x0C\x0E-\x1F]', '', xml_str) try: root = ET.fromstring(xml_str) # 处理命名空间 ns = {} if 'xmlns' in root.attrib: ns['msbuild'] = root.attrib['xmlns'] # 查找所有PackageReference package_refs = root.findall('.//msbuild:PackageReference', namespaces=ns) if ns else root.findall('.//PackageReference') # 提取Include和Version属性 result = [] for ref in package_refs: include = ref.attrib.get('Include') version = ref.attrib.get('Version') if include and version: result.append({'Include': include, 'Version': version}) return result except ET.ParseError as e: print(f"解析错误:{str(e)}") return [] except Exception as e: print(f"程序异常:{str(e)}") return []
内容的提问来源于stack exchange,提问作者nikhil
相关产品推荐
相关产品推荐

