2011-03-22 94 views
12

我需要檢查某個標籤是否存在於xml文件中。Python Lxml(objectify):檢查標籤是否存在

例如,我想看看在這個片段中存在標籤:

<main> 
     <elem1/> 
     <elem2>Hi</elem2> 
     <elem3/> 
     ... 
</main> 

目前這個樣子,我使用的是醜陋的黑客攻擊,錯誤檢查,:

try: 
    if root.elem1.tag: 
     foo = elem1 
except AttributeError: 
    foo = "error finding elem1" 

我也想要自定義字符串,如果它無法找到節點(即「無法找到-tagname-」)。

我必須檢查一長串變量,我不想重複代碼100次。

有什麼建議嗎?

編輯:

下面是實際的XML文件的剪斷:

<main> 
<asset name="Virtual Dvaered Unpresence"> 
    <virtual/> 
    <presence> 
    <faction>Dvaered</faction> 
    <value>-1000.000000</value> 
    <range>0</range> 
    </presence> 
</asset> 
<asset name="Virtual Empire Small"> 
    <virtual/> 
    <presence> 
    <faction>Empire</faction> 
    <value>100.000000</value> 
    <range>2</range> 
    </presence> 
</asset> 
</main> 

我要檢查標籤是否存在,如果是的話,得到的內容。

編輯編輯: 好吧,我要結合兩個答案,但我只能投一個答案。抱歉。

編輯3:有關XPath位置相關的問題:Python lxml (objectify): Xpath troubles

回答

5

假設你想elem2時的價值,你可以使用XPath找到它。

tree = etree.parse(StringIO(htmlString), etree.HTMLParser()).getroot() 
youWantValue = tree.xpath('/main/elem2')[0].text 
+0

如果節點不存在,會發生什麼?它會給出一個錯誤,還是一個空白值? – Biosci3c 2011-03-22 05:44:49

+0

@ Biosci3c該具體示例給出了一個錯誤,到'[0]'試圖解引用由xpath調用返回的第一個值,如果在解引用之前檢查列表是否爲空,則另一方面,您將進行一個沒有錯誤的測試。順便說一下,我發現這是所給出的最佳實踐答案。 – 2011-03-22 11:45:45

+0

好吧,我喜歡XPATH的建議,所以我也會使用它。順便說一句,我認爲你錯過了在頂部末尾的右括號線。 – Biosci3c 2011-03-28 02:39:47

1

如果你的文件往往是比較短的,你可以遍歷的<main>所有的孩子尋找標籤符合變量名的設定:

tree = lxml.etree.fromstring(DATA) 
NAMES = set(['elem1', 'elem3']) 
for node in tree.iterchildren(): 
    if node.tag in NAMES: 
     print 'found', node.tag 

或者你可以同時搜索每個變量名之一:

for tag in ('elem1', 'elem3'): 
    if tree.find(tag) is not None: 
     print 'found', tag 
+0

我一起工作的文件是相當長的。我將在這個問題中提一下它。 – Biosci3c 2011-03-22 01:58:49

+0

另外,是建立搜索範圍的第一行嗎? – Biosci3c 2011-03-22 02:03:34

6

編輯:樣本文件的更新答案。

我假設你想搜索每個資產的某些標籤。如果是的話,下面的工作對我來說:

import lxml.objectify 

# Parse the file. 
tree = lxml.objectify.parse('sample.xml') 
root = tree.getroot() 

# Which elements to find. 
to_find = set(['presence/faction', 'presence/value', 'fake']) 

# Go through each asset in the document. 
for asset in root.findall('asset'): 
    # Check for each element. 
    for name in to_find: 
     node = asset.find(name) 
     if node is not None: 
      print 'Found %s, its value is %s' % (name, node) 
     else: 
      print 'Unable to find %s' % name 

產量爲:

Found presence/value, its value is -1000.0 
Found presence/faction, its value is Dvaered 
Unable to find fake 
Found presence/value, its value is 100.0 
Found presence/faction, its value is Empire 
Unable to find fake 
+0

這看起來會很好。當我有機會時,我會嘗試。只是爲了澄清,你是否使用set()和列表作爲參數? – Biosci3c 2011-03-22 05:41:40

+0

是的。構造函數需要一個迭代器來給出集合中的初始條目。有關詳細信息,請參見[文檔](http://docs.python.org/library/stdtypes.html#set)。 – Blair 2011-03-22 23:01:19

+0

好的,有一個問題。我如何使這個賦值給特定的變量(即var_fac = presence/faction,var_value = presence/value? – Biosci3c 2011-03-27 22:24:02

23

hasattr()作品這樣的:

if hasattr(root, 'elem1'): 
    foo = root.elem1 
+2

這是我喜歡的答案。它仍然很難看,但那是Python的錯,而不是海報。我只是想檢查是否存在孩子,而不是啓動一個完整的xpath處理器。 – odigity 2013-05-29 20:03:43

+1

請注意,內部hasattr通過調用getattr和捕獲異常來工作,所以它和內部一樣難看(至少是我上次檢查的時候):) – 2015-02-24 06:21:55