ElementTree XPath - 根据属性选择元素

Posted

技术标签:

【中文标题】ElementTree XPath - 根据属性选择元素【英文标题】:ElementTree XPath - Select Element based on attribute 【发布时间】:2010-09-18 08:28:40 【问题描述】:

我在 ElementTree 中使用属性 XPath Selector 时遇到问题,根据 Documentation 应该可以做到这一点

这里有一些示例代码

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 ([)

【问题讨论】:

使用 ElementTree 1.2.6,属性 xpath 功能仅在 1.3 及更高版本中可用。 看起来 findall only 支持子集 XPath。请参阅邮件列表讨论here。 为什么要关闭它?这对我很有用......这几乎不是题外话。 【参考方案1】:

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

此类版本随 Python 2.7 或更高版本一起提供。 如果你有 Python 2.6 或更低版本,你仍然有 ElementTree 1.2.6 或更低版本。

【讨论】:

【参考方案2】:

这段代码有几个问题。

    Python 的内置 ElementTree(简称 ET)没有真正的 XPATH 支持;只有一个有限的子集 例如,它不支持 find-from-root 表达式,如//target

    注意:documentation 提到“//”,但仅限于儿童:所以表达式为 .//target 有效; //... 不是!

    还有一个替代实现:lxml,它更丰富。对于内置代码,使用文档是接缝。这不匹配/工作。

    @name 表示法选择 xml-attributes; xml 标记中的 key=value 表达式。

    所以 name-value 必须为 1 或 2 才能在给定文档中选择某些内容。或者,可以搜索带有子 element 'a' 的目标:target[a](没有@)。

对于给定的文档,使用内置 ElementTree (v1.3) 解析到 root,以下代码是正确且有效的:

root.findall(".//target") 找到两个目标 root.findall(".//target/a")找到两个a元素 root.findall(".//target[a]") 这会再次找到两个目标元素,因为它们都有一个 a 元素 root.findall(".//target[@name='1']") 只找到 first 目标。请注意需要 1 左右的引号;否则会引发 SyntaxError root.findall(".//target[a][@name='1']") 也有效;找到那个目标 root.findall(".//target[@name='1']/a") 只找到一个 a 元素; ...

【讨论】:

以上是关于ElementTree XPath - 根据属性选择元素的主要内容,如果未能解决你的问题,请参考以下文章

XML的ElementTree解析方式

Python爬虫从入门到进阶之xpath的使用

在 ElementTree 中添加前缀属性

AttributeError: 'ElementTree' 对象在尝试导入 excel 文件时没有属性 'getiterator'

XPath怎样根据一个元素定位另外一个元素?

使用 XPath,如何根据节点的文本内容和属性值来选择节点?