2010-02-18 15 views
1

我對XML和python有基本的把握,並且使用minidom取得了一些成功。我遇到了無法從XML文件中獲取所需值的情況。這是預先存在的文件的基本結構。如何過濾python中的XML文件中的值

<localization> 
    <b n="Stats"> 
     <l k="SomeStat1"> 
      <v>10</v> 
     </l> 
     <l k="SomeStat2"> 
      <v>6</v> 
     </l> 
    </b> 
    <b n="Levels"> 
     <l k="Level1"> 
      <v>Beginner Level</v> 
     </l> 
     <l k="Level2"> 
      <v>Intermediate Level</v> 
     </l> 
    </b> 
</localization> 

有大約15個不同的<b>標籤有幾十個孩子。我想要做的是,如果給定級別號碼(1),則找到相應級別的<v>節點。我只是不知道如何去做這件事。

+0

更多信息(包括示例)可能會有幫助。給定您的XML數據示例,您期望的節點的級別數爲1? –

回答

1

如果你真的只在乎尋找一個<l>標籤與特定的「K」屬性,然後獲取其<v>標籤(這就是我理解你的問題),你可以用DOM做到這一點:

from xml.dom.minidom import parseString 

xmlDoc = parseString("""<document goes here>""") 
lNodesWithLevel2 = [lNode for lNode in xmlDoc.getElementsByTagName("l") 
        if lNode.getAttribute("k") == "Level2"] 

matchingVNodes = map(lambda lNode: lNode.getElementsByTagName("v"), lNodesWithLevel2) 

print map(lambda vNode: vNode.firstChild.nodeValue, matchingVNodes) 
# Prints [u'Intermediate Level'] 

這是你的意思。

+0

我喜歡這個解決方案。我甚至不會想這樣做。 – DewBoy3d

2
#!/usr/bin/python 

from xml.dom.minidom import parseString 

xml = parseString("""<localization> 
    <b n="Stats"> 
     <l k="SomeStat1"> 
      <v>10</v> 
     </l> 
     <l k="SomeStat2"> 
      <v>6</v> 
     </l> 
    </b> 
    <b n="Levels"> 
     <l k="Level1"> 
      <v>Beginner Level</v> 
     </l> 
     <l k="Level2"> 
      <v>Intermediate Level</v> 
     </l> 
    </b> 
</localization>""") 

level = 1 
blist = xml.getElementsByTagName('b') 
for b in blist: 
    if b.getAttribute('n') == 'Levels': 
     llist = b.getElementsByTagName('l') 
     l = llist.item(level) 
     v = l.getElementsByTagName('v') 
     print v.item(0).firstChild.nodeValue; 
     #prints Intermediate Level 
0
level = "Level"+raw_input("Enter level number: ") 
content= open("xmlfile").read() 
data= content.split("</localization>") 
for item in data: 
    if "localization" in item: 
     s = item.split("</b>") 
     for i in s: 
      if """<b n="Levels">""" in i: 
       for c in i.split("</l>"): 
        if "<l" in c and level in c: 
         for v in c.split("</v>"): 
          if "<v>" in v: 
           print v[v.index("<v>")+3:] 
4

您可能會考慮使用XPATH,一種用於處理xml文檔部分的語言。

下面是使用lxml.etree的答案,它支持xpath

>>> data = """ 
... <localization> 
...  <b n="Stats"> 
...   <l k="SomeStat1"> 
...    <v>10</v> 
...   </l> 
...   <l k="SomeStat2"> 
...    <v>6</v> 
...   </l> 
...  </b> 
...  <b n="Levels"> 
...   <l k="Level1"> 
...    <v>Beginner Level</v> 
...   </l> 
...   <l k="Level2"> 
...    <v>Intermediate Level</v> 
...   </l> 
...  </b> 
... </localization> 
... """ 
>>> 
>>> from lxml import etree 
>>> 
>>> xmldata = etree.XML(data) 
>>> xmldata.xpath('/localization/b[@n="Levels"]/l[@k=$level]/v/text()',level='Level1') 
['Beginner Level'] 
+0

只是爲了咧嘴我試過這個,因爲它似乎比其他一些解決方案更有效。我有一個關於這個問題,但是,如何讓xpath返回值[''](括號和引號)? – DewBoy3d

+0

'xpath'方法返回一個字符串對象的'list'。如果沒有匹配查詢,列表將是零長度,如果我們多於一個匹配,則列表將長度爲1。你應該檢查返回對象的len或者'result [0]'並且準備好捕獲一個'IndexError'。我不知道該怎麼說'沒有引號'關於字符串對象。也許'打印結果[0]'? – MattH

0

如果你可以用BeautifulSoup庫(你能不能?),你可以用這個死簡單的代碼結束:

from BeautifulSoup import BeautifulStoneSoup 

def get_it(xml, level_n): 
    soup = BeautifulStoneSoup(xml) 
    l = soup.find('l', k="Level%d" % level_n) 
    return l.v.string 

if __name__ == '__main__': 
    print get_it(1) 

它打印Beginner Level爲您提供的示例XML。

+0

嗯,這絕對是美麗的,但我真的不想爲這個項目使用另一個庫。這幾乎已經完成了,我想回去改變一切,以適應這個新的圖書館,我沒有時間。 – DewBoy3d