2016-07-07 66 views
1

我正在使用lxml來處理在xml文件中表示的dbschema。它看起來像這樣:我可以取消引用lxml.etree.AncestorsIterator嗎?

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

當前我想查看引用,並獲取這些引用的表和列名稱。以下作品:

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

我不喜歡這樣的解決方案,因爲我知道我的nameiter只能遍歷一個元素 - 它只有一個父「表」。看來在Python中我只能在循環中使用迭代器。但我覺得有點傻。我知道我只有一個祖先「表」。我可以直接取消引用迭代器嗎?或者是否有另外一種方法來獲取這種更適合的信息?

+0

我不太明白你想要什麼,什麼是*可我取迭代器直接不知何故?*是什麼意思? ''//引用/祖先::表/ @名稱| //引用/祖先::列/ @名稱「)'會在單個查詢中得到表名和列名 –

+0

我的母語是C++,所以當我錯誤地使用了另一種語言的詞彙,我傾向於使用C++的單詞,並希望它們以可理解的方式進行映射。在C++中,如果我有第一個元素的迭代器,我可以'derefrence' - 訪問這個迭代器直接指向的對象,所以我可以跳過循環遍歷的循環,我嘗試了你的查詢,但是恐怕它的正確用法超出了我的意思,我得到了所有表和列名的列表 – Spacemoose

+0

您是否想要刪除名稱中'for n的需要?剛剛獲取以前的表名和列名?可能某些有效的輸入和預期的輸出會使它更清晰一些。 –

回答

0

您可以使用XPath來同時獲得你想要

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]) 

這將使你的祖先做:

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

或者列始終是祖父母:

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

使用你自己的邏輯,你可以在iterancetors上調用next:

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')) 
相關問題