2013-01-14 105 views
0

我需要從xml文件中提取信息,將其與xml標記之前和之後隔離,將信息存儲在字典中,然後遍歷字典以打印列表。我是一個絕對的初學者,所以我想盡可能簡單地保持它,我很抱歉,如果我描述了我想做的事情沒有多大意義。Python:將信息從xml提取到字典

這是我到目前爲止。

for line in open("/people.xml"): 
if "name" in line: 
    print (line) 
if "age" in line: 
    print(line) 

電流輸出:

 <name>John</name> 

    <age>14</age> 

    <name>Kevin</name> 

    <age>10</age> 

    <name>Billy</name> 

    <age>12</age> 

所需的輸出

Name   Age 
John   14 
Kevin   10 
Billy   12 

編輯 - 因此,使用下面的代碼,我可以得到的輸出:

{'Billy': '12', 'John': '14', 'Kevin': '10'} 

有誰知道從他這裏得到一張圖表喜歡我想要的輸出?

+3

你應該使用['xml.dom'](http://docs.python.org/2/library/xml.dom.html)。這會讓你的生活變得更輕鬆。 – inspectorG4dget

+0

我需要使用python,我特別在Mac上使用IDLE。 – user1975140

回答

1

爲此使用XML parser。例如,

import xml.etree.ElementTree as ET 
doc = ET.parse('people.xml') 
names = [name.text for name in doc.findall('.//name')] 
ages = [age.text for age in doc.findall('.//age')] 
people = dict(zip(names,ages)) 
print(people) 
# {'Billy': '12', 'John': '14', 'Kevin': '10'} 
+0

這沒有奏效,我收到一條以ParseError結尾的錯誤消息:文檔元素後面的垃圾:第44行,第0列 – user1975140

+0

請發佈您的people.xml文件的前45行。 – unutbu

+0

好的,我修正了第45行中的一個錯誤,現在我可以得到{'Billy':'12','John':'14','Kevin':'10'},但我確實需要它像頂部格式的列一樣,帶有標題。我認爲我對單詞列表的使用可能令人困惑,但是如何將這些數據放入列中? – user1975140

0

在我看來,這是在學習如何解析這個XML手動,而不是簡單地拉動庫出來的包包爲你做的練習。如果我錯了,我建議觀看史蒂夫霍夫曼的可以在這裏找到的udacity視頻:http://www.udacity.com/view#Course/cs253/CourseRev/apr2012/Unit/362001/Nugget/365002。他解釋瞭如何使用minidom模塊來解析這些輕量級xml文件。

現在,我想在我的答案中做的第一點是,你不想創建一個Python字典來打印所有這些值。 Python字典只是一組與鍵值對應的鍵。沒有對它們的排序,所以它們在文件中出現的順序遍歷是一個令人頭痛的問題。您試圖打印出所有名稱以及相應的年齡,因此數據結構(如元組列表)可能更適合整理數據。

看起來你的XML文件的結構是這樣的,每個名稱標籤都被一個與它相對應的年齡標籤成功。似乎每行只有一個名稱標籤。這使事情變得相當簡單。我不打算寫出最有效或最普遍的解決方案來解決這個問題,但我會盡可能讓代碼儘可能簡單易懂。

因此,讓我們先創建一個表來存儲數據:

那麼,讓我們創建一個表來存儲數據: 的a_list = []

現在打開你的文件,並初始化幾個變量保存每個姓名和年齡:

from __future__ import with_statement 

with open("/people.xml") as f: 
    name, age = None, None #initialize a name and an age variable to be used during traversals. 
    for line in f: 
     name = extract_name(line,name) # This function will be defined later. 
     age = extract_age(line) # So will this one. 
     if age: #We know that if age is defined, we can add a person to our list and reset our variables 
      a_list.append((name,age)) # and now we can re-initialize our variables. 
      name,age = None , None # otherwise simply read the next line until age is defined. 

現在對於文件中的每一行,我們想確定它是否包含用戶。如果確實如此,我們想提取名稱。讓我們創建用來做這樣的功能:現在

def extract_name(a_line,name): #we pass in the line as well as the name value that that we defined before beginning our traversal. 
    if name: # if the name is predefined, we simply want to keep the name at its current value. (we can clear it upon encountering the corresponding age.) 
     return name 
    if not "<name>" in a_line: #if no "<name>" in a_line, return. otherwise, extract new name. 
     return 
    name_pos = a_line.find("<name>")+6 
    end_pos = a_line.find("</name>") 
    return a_line[name_pos:end_pos] 

,我們必須創建一個函數來解析爲一個用戶的年齡線。我們可以通過類似於前一個函數的方式來做到這一點,但我們知道,一旦我們有了一個年齡,它就會立即添加到列表中。因此,我們永遠不需要關注自己以前的價值。該功能因此可能如下所示:

def extract_age(a_line): 
    if not "<age>" in a_line: #if no "<age>" in a_line: 
     return 
    age_pos = a_line.find("<age>")+5 # else extract age from line and return it. 
    end_pos = a_line.find("</age>") 
    return a_line[age_pos:end_pos] 

最後,您要打印該列表。你可以這樣做:

for item in a_list: 
    print '\t'.join(item) 

希望這對我有所幫助。我還沒有測試過我的代碼,所以它可能仍然有點bug。雖然這些概念在那裏。 :)

+0

所有好的,直到 return line [name_pos:end_pos],它說'返回'外的函數,當我縮進它,我得到'意想不到的縮進',當在前一行結尾放置冒號我得到'無效語法' 。我怕這就是我所知道的嘗試。 – user1975140

+0

哎呀,犯了一個小錯誤。在每個函數定義中,您都希望將「line」的每個實例替換爲「a_line」。現在編輯我的代碼。此外,請確保您始終使用四個空格或單個選項卡縮進您的代碼。有時python編譯器不會將它們視爲等同的。 –

+0

也注意到我已經將兩個項目而不是元組傳遞給join參數。該錯誤也應該修復。 –

3

嘗試xmldict(XML轉換到Python字典,反之亦然。):

>>> xmldict.xml_to_dict(''' 
... <root> 
... <persons> 
...  <person> 
...  <name first="foo" last="bar" /> 
...  </person> 
...  <person> 
...  <name first="baz" last="bar" /> 
...  </person> 
... </persons> 
... </root> 
... ''') 
{'root': {'persons': {'person': [{'name': {'last': 'bar', 'first': 'foo'}}, {'name': {'last': 'bar', 'first': 'baz'}}]}}} 


# Converting dictionary to xml 
>>> xmldict.dict_to_xml({'root': {'persons': {'person': [{'name': {'last': 'bar', 'first': 'foo'}}, {'name': {'last': 'bar', 'first': 'baz'}}]}}}) 
'<root><persons><person><name><last>bar</last><first>foo</first></name></person><person><name><last>bar</last><first>baz</first></name></person></persons></root>' 

或嘗試xmlmapper(與親子關係的Python字典的列表):

>>> myxml='''<?xml version='1.0' encoding='us-ascii'?> 
      <slideshow title="Sample Slide Show" date="2012-12-31" author="Yours Truly" > 
      <slide type="all"> 
       <title>Overview</title> 
       <item>Why 
        <em>WonderWidgets</em> 
        are great 
        </item> 
        <item/> 
        <item>Who 
        <em>buys</em> 
        WonderWidgets1 
       </item> 
      </slide> 
      </slideshow>''' 
    >>> x=xml_to_dict(myxml) 
    >>> for s in x: 
      print s 
    >>> 
    {'text': '', 'tail': None, 'tag': 'slideshow', 'xmlinfo': {'ownid': 1, 'parentid': 0}, 'xmlattb': {'date': '2012-12-31', 'author': 'Yours Truly', 'title': 'Sample Slide Show'}} 
    {'text': '', 'tail': '', 'tag': 'slide', 'xmlinfo': {'ownid': 2, 'parentid': 1}, 'xmlattb': {'type': 'all'}} 
    {'text': 'Overview', 'tail': '', 'tag': 'title', 'xmlinfo': {'ownid': 3, 'parentid': 2}, 'xmlattb': {}} 
    {'text': 'Why', 'tail': '', 'tag': 'item', 'xmlinfo': {'ownid': 4, 'parentid': 2}, 'xmlattb': {}} 
    {'text': 'WonderWidgets', 'tail': 'are great', 'tag': 'em', 'xmlinfo': {'ownid': 5, 'parentid': 4}, 'xmlattb': {}} 
    {'text': None, 'tail': '', 'tag': 'item', 'xmlinfo': {'ownid': 6, 'parentid': 2}, 'xmlattb': {}} 
    {'text': 'Who', 'tail': '', 'tag': 'item', 'xmlinfo': {'ownid': 7, 'parentid': 2}, 'xmlattb': {}} 
    {'text': 'buys', 'tail': 'WonderWidgets1', 'tag': 'em', 'xmlinfo': {'ownid': 8, 'parentid': 7}, 'xmlattb': {}} 
上面的代碼將會生成

。當你迭代它時;您將獲得dict密鑰的信息;如tag,text,xmlattb,tailxmlinfo中的附加信息。這裏root元素將有parentid信息作爲0

+0

xmldict有bug,>>> xml_to_dict(''' love''')生成{'i':{'t':'love'}}。屬性type =「all」消失了。 –

0

下面是使用LXML庫的另一種方式:

from lxml import objectify 


def xml_to_dict(xml_str): 
    """ Convert xml to dict, using lxml v3.4.2 xml processing library, see http://lxml.de/ """ 
    def xml_to_dict_recursion(xml_object): 
     dict_object = xml_object.__dict__ 
     if not dict_object: # if empty dict returned 
      return xml_object 
     for key, value in dict_object.items(): 
      dict_object[key] = xml_to_dict_recursion(value) 
     return dict_object 
    return xml_to_dict_recursion(objectify.fromstring(xml_str)) 

xml_string = """<?xml version="1.0" encoding="UTF-8"?><Response><NewOrderResp> 
<IndustryType>Test</IndustryType><SomeData><SomeNestedData1>1234</SomeNestedData1> 
<SomeNestedData2>3455</SomeNestedData2></SomeData></NewOrderResp></Response>""" 

print xml_to_dict(xml_string) 

要保留父節點,而不是使用:

def xml_to_dict(xml_str): 
    """ Convert xml to dict, using lxml v3.4.2 xml processing library, see http://lxml.de/ """ 
    def xml_to_dict_recursion(xml_object): 
     dict_object = xml_object.__dict__ 
     if not dict_object: # if empty dict returned 
      return xml_object 
     for key, value in dict_object.items(): 
      dict_object[key] = xml_to_dict_recursion(value) 
     return dict_object 
    xml_obj = objectify.fromstring(xml_str) 
    return {xml_obj.tag: xml_to_dict_recursion(xml_obj)} 

如果你希望只返回一個子樹並將其轉換爲字典,你可以使用Element.find()

xml_obj.find('.//') # lxml.objectify.ObjectifiedElement instance 

請參閱lxml documentation