如何在带XML命名空间的ElementTree中遍历根节点获取ClsItems标签
问题原因
你遇到的问题是XML根节点定义了无前缀的默认命名空间,所有未加前缀的标签都会自动归属到该命名空间下,直接搜索ClsItems无法匹配的原因是标签实际的完整标识为{http://ws.comax.co.il/Comax_WebServices/}ClsItems,并非单纯的ClsItems。
解决方案
方案1:显式声明命名空间映射(推荐)
这是符合XML规范的处理方式,不会修改原XML结构:
- 自定义命名空间字典,给默认命名空间绑定一个自定义前缀
- 所有
find/findall查询时,标签前加自定义前缀,同时传入命名空间参数
import xml.etree.ElementTree as ET # 命名空间映射:自定义前缀对应XML里的默认命名空间地址 ns = { "ws": "http://ws.comax.co.il/Comax_WebServices/" } tree = ET.parse(xml_path) root = tree.getroot() # 注意原XML中ID字段是大写,和标签名保持一致 product_dict = { "Name": [], "Size": [], 'ID': []} # 查询时添加前缀,传入命名空间参数 for idx, item in enumerate(root.findall('.//ws:ClsItems', namespaces=ns)): for field in product_dict.keys(): # 子字段查询也需要加命名空间前缀 field_node = item.find(f'ws:{field}', namespaces=ns) product_dict[field].append(field_node.text if field_node is not None else None)
方案2:统一清除命名空间前缀
如果不想每次查询都加前缀,可以先批量移除所有标签的命名空间标识,直接沿用你原来的代码逻辑:
import xml.etree.ElementTree as ET def remove_namespace(tree): for elem in tree.iter(): # 拆分标签中的命名空间前缀,保留原始标签名 if '}' in elem.tag: elem.tag = elem.tag.split('}', 1)[1] return tree tree = ET.parse(xml_path) root = remove_namespace(tree).getroot() # 后续直接使用你原有的逻辑即可 headers = [] product_dict = { "Name": [], "Size": [], 'ID': []} for idx, item in enumerate(root.findall('.//ClsItems')): if idx == 0: headers = [x.tag for x in list(item)] for h in headers: if h in product_dict: product_dict[h].append(item.find(h).text)
注意:你原有代码中
product_dict的键写为小写开头的Id,但XML中对应标签是大写ID,大小写不匹配会导致取值失败,需要修正字段名。
内容的提问来源于stack exchange,提问作者gil
相关产品推荐
相关产品推荐

