为什么XML的.findall方法无法正确读取节点,返回了多余匹配结果?
问题原因
- XPath表达式中的
//是递归深度查找标识符,会匹配当前节点下所有层级的对应节点,不限制为直接子级:- 开头的
.//{urn:schemas-upnp-org:device-1-0}serviceList会匹配选中的device节点下所有层级的serviceList节点,除了当前device的直接子节点serviceList,还会命中嵌套在子device中的所有serviceList - 后续的
//{urn:schemas-upnp-org:device-1-0}serviceType同样会在每个匹配到的serviceList下递归查找所有serviceType,因此会返回值为2、3的结果
- 开头的
修正方案
要匹配直接子节点,将递归查找符//替换为单级匹配符/即可。为了简化命名空间写法,可先注册命名空间前缀,修正后代码如下:
import os import sys import xml.etree.ElementTree as ET # 注册UPNP命名空间,简化后续路径写法 ns = {'upnp': 'urn:schemas-upnp-org:device-1-0'} root = ET.fromstring(inner_xml) # inner_xml为上述XML内容 device = root.find('upnp:device', ns) # 路径规则:./代表当前device节点,/表示仅匹配直接子节点 for serviceType in device.findall('./upnp:serviceList/upnp:service/upnp:serviceType', ns): print(serviceType.text)
如果不想注册命名空间,也可以直接使用全量命名空间写法,路径改为:./{urn:schemas-upnp-org:device-1-0}serviceList/{urn:schemas-upnp-org:device-1-0}service/{urn:schemas-upnp-org:device-1-0}serviceType
运行后仅会输出1,符合需求。
内容的提问来源于stack exchange,提问作者Algo
相关产品推荐
相关产品推荐

