2016-07-07 38 views
1

私はxmlファイルで表現されたdbschemaを操作するためにlxmlを使用しています。これは次のようになります。lxml.etree.AncestorsIteratorを逆参照できますか?

<Tables> 
<Table name = "table1"> 
<Columns> 
<Column name="COL1">...</Column> 
<Column name="COL2">... 
    <References> 
    <Reference>TABLENAME</Reference> 
    </References> 
</Column> 
</Table> 
... 
</Tables> 

現在、私は参照を見て、それらの参照の表と列の名前を取得したいと考えています。次の作品は:私は私のnameiterは、単一の要素を反復処理できることを知っているので

refiter = mytree.iter("Reference") 
for r in refiter: 
    nameiter =r.iterancestors("Table") 
    for n in nameiter: 
     tablename = .get("name") 

私は、このソリューションを好きではない - それは唯一の親「表」を持っています。 Pythonではループ内のイテレータしか使用できないようです。しかし、私はそれがちょっとばかだと思います。私は祖先「テーブル」が1つしかないことを知っています。イテレータを直接何とか逆参照できますか?あるいは、この情報を入手するための別の方法が適していますか?

+0

私はあなたが望むものに従わない、何か*私はイテレータを直接何とか逆参照できますか? //参照/ ancestor ::テーブル/ @ name | //リファレンス/ ancestor :: Column/@ name ")'は単一のクエリでテーブル名とカラム名の両方を取得します –

+0

母国語はC++です。私は別の言葉でボキャブラリーを紛失しています。私はC++の言葉を使う傾向があり、理解しやすい方法でマップすることを願っています。反復子が直接指し示すオブジェクトです。ループオーバーループをスキップするだけでよいのですが、クエリを試しましたが、正しい使用法が私を超えていたことが心配です。すべてのテーブル名と列名のリストを取得しました...あなたが望むものではありません。 – Spacemoose

+0

'name in in n 'の必要性を取り除きたいと思っていますか?以前のテーブルとカラムの名前を取得するだけですか? –

答えて

0

あなたは、あなたを与えるだろうどの

x = """<?xml version="1.0" encoding="utf-8"?> 
<Tables> 
<Table name = "table1"> 
<Columns> 
<Column name="COL1">...</Column> 
<Column name="COL2">... 
    <References> 
    <Reference>TABLENAME</Reference> 
    </References> 
</Column> 
</Columns> 
</Table> 
<Table name = "table2"> 
<Columns> 
<Column name="COL2">...</Column> 
<Column name="COL3">... 
    <References> 
    <Reference>TABLENAME</Reference> 
    </References> 
</Column> 
</Columns> 
</Table> 
</Tables>""" 


import lxml.etree as et 

xml = et.fromstring(x) 

refs = xml.iter("Reference") 
print([(ref.xpath("./ancestor::Table/@name")[0], ref.xpath("./ancestor::Column/@name")[0]) for ref in refs]) 

をしたいの祖先の両方を取得するために、XPathを使用してそれを行うことができます。

[('table1', 'COL2'), ('table2', 'COL3')] 

または列が常に祖父母されている場合:

[(ref.xpath("./ancestor::Table/@name")[0], ref.xpath("./../../@name")[0]) for ref in refs] 

独自のロジックを使用すると、iterancetorsで次のように呼び出すことができます。

あなたを与えるだろう
refs = xml.iter("Reference") 


for r in refs: 
    print(next(r.iterancestors("Table")).get("name")) 
    print(next(r.iterancestors("Column")).get("name")) 

:あなたはイテレータの最初の結果に興味を持っていたよう

table1 
COL2 
table2 
COL3 
0

、あなたは最初の要素を取得するためにnextメソッドを使用し、かつ不明瞭/不要を回避することができますforループ。

xml_string = """ 
<Tables> 
<Table name = "table1"> 
<Columns> 
<Column name="COL1">...</Column> 
<Column name="COL2">... 
    <References> 
    <Reference>TABLENAME</Reference> 
    </References> 
</Column> 
</Columns> 
</Table> 
<Table name = "table2"> 
<Columns> 
<Column name="COL2">...</Column> 
<Column name="COL3">... 
    <References> 
    <Reference>TABLENAME</Reference> 
    </References> 
</Column> 
</Columns> 
</Table> 
</Tables>""" 


import lxml.etree as ETree 

root = ETree.fromstring(bytes(xml_string, 'UTF-8')) 

refiter = root.iter('Reference') 
for r in refiter: 
    nameiter = r.iterancestors('Table') 
    name = next(nameiter).get('name') 
    print(name) 

インデックスで結果にアクセスする場合は、まずイテレータからリストを生成できます。

tables = list(r.iterancestors('Table')) 
print(tables[0].get('name')) 
関連する問題