ElementTree XPath - 根据属性选择元素

50

我在使用ElementTree的XPath选择器属性时遇到了困难,根据文档,我应该能够这样做。

下面是一些示例代码

XML

<root>
 <target name="1">
    <a></a>
    <b></b>
 </target>
 <target name="2">
    <a></a>
    <b></b>
 </target>
</root>

Python

:Python是一种高级编程语言,常被用于Web开发、数据分析、人工智能等领域。

def parse(document):
    root = et.parse(document)
    for target in root.findall("//target[@name='a']"):
        print target._children

我收到了以下异常:

expected path separator ([)

1
使用ElementTree 1.2.6,属性xpath功能仅在1.3及以上版本中可用。 - Nick Stinemates
似乎findall仅支持XPath的子集。请参阅此处的邮件列表讨论(https://mailman-mail5.webfaction.com/pipermail/lxml/20060526/009219.html)。 - Mike Marshall
17
为什么要关闭它?它对我很有用... 它几乎没有离题。 - daramarak
2个回答

37

您正在尝试使用的语法是在 ElementTree 1.3 中新增的。

此版本随 Python 2.7 或更高版本一起发布。 如果您使用的是 Python 2.6 或更低版本,则仍将使用 ElementTree 1.2.6 或更早版本。


34

这段代码存在几个问题。

  1. Python内置的ElementTree(简称ET)没有真正的XPATH支持;只有一小部分功能。例如,它不支持像//target这样的从根目录开始查找的表达式。

    注意:文档中提到了"//",但仅适用于子元素:因此,.//target是有效的;//...则不行!

    有一种替代实现方式:lxml,它更加丰富。看起来官方文档是用于内置代码的。但这并不匹配/适用。

  2. @name符号选择XML属性;在XML标签中的key=value表达式。

    因此,名称-值必须是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周围加上引号;否则会引发SyntaxError
  • root.findall(".//target[a][@name='1']") 也是有效的;用于查找该目标
  • root.findall(".//target[@name='1']/a") 仅查找一个a元素; ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接