2017-06-23 85 views
0

我有这个xml文件,它包含和里面。尽管我只获得第一个,但我无法循环。下面是XML结构和代码:在Python中提取数据XML - > DICT

from lxml import objectify as xml_objectify 
contents = open('/home/conacons/Documents/order.xml').read() 
def xml_to_dict(xml_str): 
""" Convert xml to dict, using lxml v3.4.2 xml processing library """ 
    def xml_to_dict_recursion(xml_object): 
     dict_object = xml_object.__dict__ 
     if not dict_object: 
      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(xml_objectify.fromstring(xml_str)) 
xml_dict = xml_to_dict(contents) 
#print xml_dict 
for item,v in xml_dict['item']['items'].items(): 
    print item,v 
<Order> 
<item> 
<customer></customer> 
<status>no</status> 
<amount_untaxed>7315.0</amount_untaxed> 
<name>Test/001</name> 
<confirmation_date>False</confirmation_date> 
<order_id>8</order_id> 
<items> 
<item><list_price>16.5</list_price><description>False</description><weight>0.0</weight><default_code/><id>18</id><uom>Unit(s)</uom> <name>iPod</name></item><item><list_price>12.5</list_price><description>False</description><weight>0.0</weight><default_code>M-Wir</default_code><id>19</id><uom>Unit(s)</uom><name>Mouse, Wireless</name>  </item> 

Whrn我运行这段代码,我只得到了项目之一。我如何让循环获取项目中的所有项目? THanks (输出): item {'list_price':16.5,'description':'False','weight':0.0,'default_code':u'','id':18,'uom':'单位s)','name':'iPod'

+0

你能发布一个有效的xml文档吗?这一个有一些错误。例如,订单,第一个“item”标签等没有结束标签。 –

+0

以下是完整的order.xml文档 https://pastebin.com/sUsbRqAz –

+0

您可以使用xml并通过xml库处理它或使用json并将其转换为字典进行处理。将xml转换为dict进行处理通常是一个糟糕的主意。 – marbu

回答

0

您的方法存在问题。 XML对象不会转换为dict,因为dict对象不能有重复的键。例如,在您的情况下,如果您拨打xml_object.__dict__xml_object与几个item儿童标记,它将返回一个dict只有一个item键。所以你应该使用getchildren方法而不是__init__。但还有另一个问题。对于与items标签xml_object从例如下面的代码也将无法正常工作:

for child in xml_object.getchildren(): 
    dict_object[child.tag] = xml_to_dict_recursion(child) 

你理解的原因是,在child.tag具有相同值的循环迭代。

解决这些问题的一种可能的方法是使用collections.defaultdict。该代码可能是这个样子:

from collections import defaultdict 
from lxml import objectify 


def xml_to_dict(xml_str): 
    def xml_to_dict_recursion(xml_object): 
     dict_object = defaultdict(list) 
     if not xml_object.__dict__: 
      return xml_object 
     for child in xml_object.getchildren(): 
      dict_object[child.tag].append(xml_to_dict_recursion(child)) 
     return dict_object 
    return xml_to_dict_recursion(objectify.fromstring(xml_str)) 


if __name__ == "__main__": 
    contents = open('input.xml').read() 
    xml_dict = xml_to_dict(contents) 
    for value in xml_dict['item'][0]['items'][0]['item']: 
     print(dict(value)) 

在这种情况下,输出是:

{'uom': ['Unit(s)'], 'default_code': [''], 'description': ['False'], 'name': ['iPod'], 'weight': [0.0], 'list_price': [16.5], 'id': [18]} 
{'uom': ['Unit(s)'], 'default_code': ['M-Wir'], 'description': ['False'], 'name': ['Mouse, Wireless'], 'weight': [0.0], 'list_price': [12.5], 'id': [19]} 

但在我看来,这种做法是不那么方便易和更舒适的方式只是解析XML文档本身lxml.objectify(见docs)。例如:

tree = objectify.parse('input.xml') 
order = tree.getroot() 
order_items = order.getchildren() 
for order_item in order_items: 
    print(order_item['amount_untaxed']) 
    customer = order_item['customer'] 
    print(customer['item']['city']) 
    for item in order_item['items'].getchildren(): 
     print(item['list_price']) 
+0

酷感谢家伙这个作品。现在因为这将是一个多订单进口系统,我将在以及这里的另一个中有一个以上的项目。我可以通过'在xml_dict ['item'] [0] ['items'] [0] ['item']中为value访问它们: #print value ['list_price'] print(dict(value)) 对于xml_dict中的值['item'] [1] ['items'] [0] ['item']: #print value ['list_price'] print(dict(value))' 但是要遍历所有他们手动编写xml_dict ['item'] [1] [或xml_dict ['item'] [2] [或xml_dict ['item'] [3] [?在此先感谢 –

+0

你真的需要在转换XML对象字典?在我看来,使用'lxml'方法更方便。 –

+0

好吧,简而言之,如何在不将xml转换为字典的情况下访问订单中的所有订单和项目?非常感谢 –