Python中XPath查找含指定文本的任意属性元素报错求助
问题描述
用户有如下XML文档:
<RootNode> <SubNode name="MainNode" SubNodeID="1"> <SubSubNode SubSubID="10" SubSubName="Product Food"> <Item subItemID="100" ItemName="Apple" OtherName="Gala"/> <Item subItemID="101" ItemName="Apple" OtherName="Aroma"/> <Item subItemID="102" ItemName="Pear" OtherName="Williams"/> <Item subItemID="103" ItemName="Pear" OtherName="Abate"/> <Item subItemID="104" ItemName="Cranberry" OtherName="Bilberry"/> <Item subItemID="105" ItemName="Cranberry" OtherName="Bluberries"/> <Item subItemID="106" ItemName="Strawberry" OtherName="Berry"/> <Item subItemID="107" ItemName="Peach" OtherName="Nectarina"/> </SubSubNode> <SubSubNode SubSubID="20" SubSubName="Product Beverage"> <Item subItemID="108" ItemName="Cola" OtherName="Coca cola"/> <Item subItemID="109" ItemName="Cola" OtherName="Pepsi"/> <Item subItemID="110" ItemName="Orange Juice" OtherName="Fanta"/> <Item subItemID="111" ItemName="Soft drink" OtherName="Grape soda"/> <Item subItemID="112" ItemName="Soft drink" OtherName="Orange soda"/> <Item subItemID="113" ItemName="Soft drink" OtherName="Grape soda"/> </SubSubNode> </SubNode> </RootNode>
使用Python标准库加载文档:
import xml.etree.ElementTree as ET tree = ET.parse('Food.xml') root = tree.getroot()
可以正常用XPath查找特定属性值的元素:
xPath = "SubNode/SubSubNode/Item[@OtherName='Gala']" print(len(root.findall(xPath)))
但尝试用XPath查找任意属性包含指定文本的元素时,执行代码报错SyntaxError: invalid predicate,出错代码如下:
search_text = "berry" xpath_expr = ".//*[@*[contains(., '{search_text}')]]"
解决办法
原因
Python标准库的xml.etree.ElementTree仅支持XPath 1.0的子集,不支持@*[contains(., 'xxx')]这种对任意属性使用contains()的语法,这是报错的核心原因。
方案1:使用lxml库(推荐)
lxml库支持完整的XPath 1.0语法,可以直接运行目标表达式。
操作步骤:
- 安装lxml:
pip install lxml
- 修改代码:
from lxml import etree tree = etree.parse('Food.xml') root = tree.getroot() search_text = "berry" # 用f-string格式化表达式,注意单引号的转义 xpath_expr = f".//*[@*[contains(., '{search_text}')]]" matches = root.xpath(xpath_expr) print(f"找到 {len(matches)} 个匹配元素") for elem in matches: print(f"元素标签:{elem.tag},属性:{elem.attrib}")
方案2:不换库,手动遍历元素和属性
如果不想引入第三方库,可以遍历所有元素,逐个检查属性值是否包含目标文本:
import xml.etree.ElementTree as ET tree = ET.parse('Food.xml') root = tree.getroot() search_text = "berry" matches = [] # 遍历所有层级的元素 for elem in root.iter(): # 检查当前元素的每个属性 for attr_name, attr_value in elem.attrib.items(): # 可根据需求决定是否忽略大小写 if search_text.lower() in attr_value.lower(): matches.append(elem) break # 找到匹配属性后停止检查当前元素的其他属性 print(f"找到 {len(matches)} 个匹配元素") for elem in matches: print(f"元素标签:{elem.tag},属性:{elem.attrib}")
说明:
- 方案2的代码可实现和目标XPath完全相同的效果,还能灵活添加忽略大小写等自定义逻辑。
- 如果需要严格匹配大小写,去掉代码中的
.lower()即可。
内容的提问来源于stack exchange,提问作者user1732337
相关产品推荐
相关产品推荐

