【问题标题】:Xpath select attribute of current node?当前节点的Xpath选择属性?
【发布时间】:2011-12-07 01:26:01
【问题描述】:

我使用 python 和 lxml 来处理 xml。在我查询/过滤以到达我想要的节点后,但我遇到了一些问题。如何通过 xpath 获取其属性的值?这是我的输入示例。

>print(etree.tostring(node, pretty_print=True ))
<rdf:li xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"  rdf:resource="urn:miriam:obo.chebi:CHEBI%3A37671"/>

我想要的值在 resource=... 中。目前我只是使用 lxml 来获取值。我想知道是否可以在纯 xpath 中进行?谢谢

编辑:忘了说,这不是根节点,所以我不能在这里使用 //。我在 xml 文件中有 2000-3000 个其他人。我的第一次尝试是使用“.@attrib”和“self::*@”,但这些似乎不起作用。

EDIT2:我会尽力解释(嗯,这是我第一次使用 xpath 处理 xml 问题。英语不是我最喜欢的领域之一......)。这是我的输入 sn-p http://pastebin.com/kZmVdbQQ (来自这里的完整一个 http://www.comp-sys-bio.org/yeastnet/ 使用版本 4)。

在我的代码中,我尝试使用资源链接 chebi(&lt;rdf:li rdf:resource="urn:miriam:obo.chebi:...."/&gt;).如果我从像 speciesTypes 这样的父节点开始,很容易在子节点中获取属性,但我想知道如果我从 rdf:li 开始怎么办。据我了解,xpath 中的“//”不仅会从任何地方寻找节点在当前节点中。

下面是我的代码

import lxml.etree as etree

tree = etree.parse("yeast_4.02.xml")
root = tree.getroot()
ns = {"sbml": "http://www.sbml.org/sbml/level2/version4", 
      "rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
      "body":"http://www.w3.org/1999/xhtml",
      "re": "http://exslt.org/regular-expressions"
      }
#good enough for now
maybemeta = root.xpath("//sbml:speciesType[descendant::rdf:li[starts-with(@rdf:resource, 'urn:miriam:obo.chebi') and not(starts-with(@rdf:resource, 'urn:miriam:uniprot'))]]", namespaces = ns)

def extract_name_and_chebi(node):
    name = node.attrib['name']
    chebies = node.xpath("./sbml:annotation//rdf:li[starts-with(@rdf:resource, 'urn:miriam:obo.chebi') and not(starts-with(@rdf:resource, 'urn:miriam:uniprot'))]", namespaces=ns) #get all rdf:li node with chebi resource
    assert len(chebies) == 1
    #my current solution to get rdf:resource value from rdf:li node
    rdfNS = "{" + ns.get('rdf') + "}"
    chebi = chebies[0].attrib[rdfNS + 'resource'] 
    #do protein later
    return (name, chebi)

    metaWithChebi = map(extract_name_and_chebi, maybemeta)
fo = open("metabolites.txt", "w")

for name, chebi in metaWithChebi:
    fo.write("{0}\t{1}\n".format(name, chebi))

【问题讨论】:

  • 用 xpath 解析 rdf xml 真的不是一个好主意。 XML 是树,而 RDF 是图,可以用不同的 rdfxml 表示同一个 rdf 图。您应该将 xml 视为一种交换格式,并使用 RDF 库从 XML 创建图形,然后直接使用图形。
  • 感谢您的建议。但在这项工作中,我只想提取包含一些信息的节点,然后对其进行一些格式处理以在电子表格中使用。

标签: python xpath attributes sbml


【解决方案1】:

在 XPath 查询中使用 @ 前缀属性名称:

>>> from lxml import etree
>>> xml = """\
... <?xml version="1.0" encoding="utf8"?>
... <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
...     <rdf:li rdf:resource="urn:miriam:obo.chebi:CHEBI%3A37671"/>
... </rdf:RDF>
... """
>>> tree = etree.fromstring(xml)
>>> ns = {'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'}
>>> tree.xpath('//rdf:li/@rdf:resource', namespaces=ns)
['urn:miriam:obo.chebi:CHEBI%3A37671']

编辑

这是问题中脚本的修订版本:

import lxml.etree as etree

ns = {
    'sbml': 'http://www.sbml.org/sbml/level2/version4',
    'rdf':'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
    'body':'http://www.w3.org/1999/xhtml',
    're': 'http://exslt.org/regular-expressions',
    }

def extract_name_and_chebi(node):
    chebies = node.xpath("""
        .//rdf:li[
        starts-with(@rdf:resource, 'urn:miriam:obo.chebi')
        ]/@rdf:resource
        """, namespaces=ns)
    return node.attrib['name'], chebies[0]

with open('yeast_4.02.xml') as xml:
    tree = etree.parse(xml)

    maybemeta = tree.xpath("""
        //sbml:speciesType[descendant::rdf:li[
        starts-with(@rdf:resource, 'urn:miriam:obo.chebi')]]
        """, namespaces = ns)

    with open('metabolites.txt', 'w') as output:
        for node in maybemeta:
            output.write('%s\t%s\n' % extract_name_and_chebi(node))

【讨论】:

  • 忘了说,这不是根节点,所以我不认为“//”在这里工作
  • @Tg。我不明白您的评论或您添加到问题中的编辑。你的xml文件的结构是什么?您目前使用什么代码来解析和查询它?如果您发布了一个像我的答案中那样的小型工作示例脚本,那么人们提供更有用的答案会容易得多。
  • @Tg。我已经用您问题中脚本的修订版本更新了我的答案。它产生完全相同的输出。
  • 谢谢,我稍后再调查。
【解决方案2】:

要从当前节点中选择其名为 rdf:resource 的属性,请使用此 XPath 表达式

@rdf:resource

为了“正常工作”,您必须将前缀 "rdf:" 的关联注册到相应的命名空间。

如果你不知道如何注册 rdf 命名空间,仍然可以选择属性——用这个 XPath 表达式:

@*[name()='rdf:resource']

【讨论】:

    【解决方案3】:

    嗯,我明白了。我在这里需要的 xpath 表达式是“./@rdf:resource”而不是“.@rdf:resource”。但为什么 ?我认为“./”表示当前节点的子节点。

    【讨论】:

    • 属性也是子节点!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-30
    • 1970-01-01
    • 2012-03-24
    • 2010-11-22
    • 1970-01-01
    相关资源
    最近更新 更多