在python xpath中根据另一个的值选择xml节点

时间:2015-02-21 18:33:58

标签: python xml xpath

我正在尝试基于另一个节点选择XML中的节点这里是我的XML样本

<?xml version="1.0"?>
<gameList>
    <game>
        <name>Cave Story</name>
        <lastplayed>1</lastplayed>
    </game>
    <game>
        <name>Doom</name>
        <lastplayed>2</lastplayed>
    </game>
    <game>
        <name>Duke Nukem 3D</name>
    </game>
</gameList>

我已经有代码来找到<lastplayed>的最高值,并将其存储为最新版但我正在努力使用XPath来获取匹配的名称。我正在使用python,我认为XPath将是

//gameList/game/[lastplayed=newest]/name"

但是当我尝试在python中输出它时,它似乎无法工作。

import lxml.etree as ET
root = ET.parse("./gamelist.xml")
newest = 2
gname = root.xpath(".//gamelist/game/[lastplayed=newest]/name")

此时我得到XPathEvalError: Invalid expression

我觉得有一些小的我不知道为什么这对我不起作用。

注意:为了简化,我已经手动声明了最新版本,但这可以通过我已有的一些编码来完成,并且这个XML文档确实从另一个程序更改了所以我无法更改条目的顺序

1 个答案:

答案 0 :(得分:0)

您的尝试有两个问题:

    XPath表达式中的
  • newest不是动态的;它未与代码中的newest变量相关联。

  • 您正在使用语法在标记上查找属性,而不是在标记中查找文本内容

因此,您正在寻找属性lastplayed等于newest的内容。没有这样的匹配,你的表达不完整。

要将lastplayed元素与特定文字匹配,请使用[lastplayed/text()="specific text"]。您必须使用Python字符串格式化才能将newest的值放入该表达式中。您正在寻找兄弟匹配,所以选择子元素文本匹配的元素:

root.xpath(".//game[lastplayed/text()='{}']/name/text()".format(newest))

我已离开gameList(区分大小写!)根目录,无需在此处将搜索限制为根目录。

因此,这会查找<game>元素与您的特定文本具有<lastplayed>子元素。找到后,它会选择<name>子元素,从该标记中获取文本:

>>> import lxml.etree as ET
>>> sample = '''\
... <?xml version="1.0"?>
... <gameList>
...     <game>
...         <name>Cave Story</name>
...         <lastplayed>1</lastplayed>
...     </game>
...     <game>
...         <name>Doom</name>
...         <lastplayed>2</lastplayed>
...     </game>
...     <game>
...         <name>Duke Nukem 3D</name>
...     </game>
... </gameList>
... '''
>>> root = ET.fromstring(sample)
>>> root.xpath(".//game[lastplayed/text()='{}']/name/text()".format(newest))
['Doom']