ElementTree XPath - 根据属性选择元素
我在使用ElementTree中的属性XPath选择器时遇到了问题,按照文档的说法,我应该能够做到这一点。
这里有一些示例代码:
XML
<root>
<target name="1">
<a></a>
<b></b>
</target>
<target name="2">
<a></a>
<b></b>
</target>
</root>
Python
def parse(document):
root = et.parse(document)
for target in root.findall("//target[@name='a']"):
print target._children
我收到了以下异常:
expected path separator ([)
2 个回答
34
这段代码有几个问题。
Python自带的ElementTree(简称ET)并不真正支持XPATH,只支持一些有限的功能。举个例子,它不支持从根节点查找的表达式,比如
//target
。需要注意的是,文档提到过"//",但仅限于子节点:所以像
.//target
这样的表达式是有效的;而//...
则不是!还有一个替代的实现方式:lxml,它功能更强大。看起来文档是针对内置代码的,但这并不匹配/有效。
在
@name
的写法中,选择的是xml的属性;而key=value
的表达式是在xml标签内的。所以这个名字-值对必须是1或2,才能在给定的文档中选择某个东西。或者,可以查找有子元素 'a'的目标:
target[a]
(不需要@)。
对于给定的文档,使用内置的ElementTree(v1.3)解析到根节点,以下代码是正确且有效的:
root.findall(".//target")
查找所有目标root.findall(".//target/a")
查找两个a元素root.findall(".//target[a]")
这会再次找到所有目标,因为它们都有一个a元素root.findall(".//target[@name='1']")
只查找第一个目标。注意,1周围的引号是必须的;否则会出现语法错误root.findall(".//target[a][@name='1']")
也是有效的;用来查找那个目标root.findall(".//target[@name='1']/a")
只查找一个a元素;...
36
你想用的语法是在ElementTree 1.3中新增的。
这个版本是和Python 2.7或更高版本一起提供的。如果你使用的是Python 2.6或更低版本,那你还是在用ElementTree 1.2.6或更低的版本。