4

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の問題に対処するのはこれが初めてです。英語は私のお気に入りの分野の1つではありません....)。ここに私の入力スニペットhttp://pastebin.com/kZmVdbQQ (バージョン 4 を使用したhttp://www.comp-sys-bio.org/yeastnet/からの完全なもの) があります。

私のコードでは、リソース リンク chebi ( を使用して種タイプ ノードを取得しようとしまし<rdf:li rdf:resource="urn:miriam:obo.chebi:...."/>)た。次に、rdf:li の rdf:resource 属性から値を取得しようとしました。つまり、child で属性を取得するのは簡単だと確信しています。種型のように親ノードから始めるとノードを探すのですが、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))
4

3 に答える 3

3

@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))
于 2011-12-07T02:12:41.740 に答える
1

という名前の現在のノードの属性を選択するには、次のrdf:resourceXPath 式を使用します

@rdf:resource

これが「正しく機能する」ためには"rdf:"、対応する名前空間へのプレフィックスの関連付けを登録する必要があります。

rdf 名前空間を登録する方法がわからない場合でも、次のXPath 式を使用して属性を選択できます。

@*[name()='rdf:resource']
于 2011-12-07T13:34:58.893 に答える
0

さて、私はそれを手に入れました。ここで必要な xpath 式は、「.@rdf:resource」ではなく「./@rdf:resource」です。しかし、なぜ ?「./」は現在のノードの子を示していると思いました。

于 2011-12-07T20:39:22.457 に答える