如何在Python中正确解析字符串格式的XML数据
问题原因
你的XML解析失败的核心原因是XML内容携带默认命名空间,和XML头部声明无关。xml.etree.ElementTree处理带命名空间的XML时,会自动将命名空间URI拼接在标签名前,你直接按原始标签名检索节点时会匹配不到。
你提供的XML包含两个层级的默认命名空间:
- 外层
rpc-reply节点的默认命名空间:urn:ietf:params:xml:ns:netconf:base:1.0 - 内层
config节点的默认命名空间:http://www.calix.com/ns/exa/base
你提供的简化测试代码里的XML已经去掉了所有命名空间属性,本身是可以正常解析的,运行后会输出
config {},如果这段代码运行异常,检查是否有特殊字符或格式错误。
解决方法
方法1:注册命名空间后按路径查询(推荐)
先定义命名空间映射表,查询节点时携带命名空间前缀,兼容性最好:
import xml.etree.ElementTree as ET # 命名空间映射,前缀可以自定义,URI必须和XML里的定义完全一致 ns = { "netconf": "urn:ietf:params:xml:ns:netconf:base:1.0", "calix": "http://www.calix.com/ns/exa/base" } # 解析完整的原始XML内容 root = ET.fromstring(完整XML字符串) # 示例:获取所有policy-map节点 policy_maps = root.findall(".//calix:policy-map", ns) for pm in policy_maps: # 获取策略映射名称 pm_name = pm.find("calix:name", ns).text # 获取对应EIR值 eir_val = pm.find(".//calix:eir", ns).text print(f"策略名称:{pm_name},EIR:{eir_val}")
方法2:清除所有命名空间
如果不需要区分命名空间,可以先清除所有节点的命名空间标识,之后直接用原始标签名查询即可:
import xml.etree.ElementTree as ET def clear_namespaces(root): for elem in root.iter(): # 清除标签中的命名空间 if "}" in elem.tag: elem.tag = elem.tag.split("}", 1)[1] # 清除属性中的命名空间 for attr in list(elem.attrib.keys()): if "}" in attr: val = elem.attrib.pop(attr) elem.attrib[attr.split("}", 1)[1]] = val return root # 解析XML后先调用清除函数 root = ET.fromstring(完整XML字符串) root = clear_namespaces(root) # 之后可以直接用原始标签名查询 policy_maps = root.findall(".//policy-map") for pm in policy_maps: pm_name = pm.find("name").text eir_val = pm.find(".//eir").text print(pm_name, eir_val)
内容的提问来源于stack exchange,提问作者Mellgood
相关产品推荐
相关产品推荐

