XML 到字典/数据帧



我现在正在学习python,我已经成功地将CSV与Pandas数据帧一起使用,但是我现在正在尝试使用XML,但是我没有弄清楚如何从XML中的元素中"选择"数据。

我的 XML 文件如下所示:

<DATABASE>
    <OBJECT>
        <PROPERTY NAME="__type" VALUE=".com.infoblox.dns.bind_a"/>
        <PROPERTY NAME="address" VALUE="192.168.10.1"/>
    </OBJECT>
    <OBJECT>
        <PROPERTY NAME="__type" VALUE=".com.infoblox.dns.bind_a"/>
        <PROPERTY NAME="address" VALUE="192.168.20.1"/>
    </OBJECT>
    <OBJECT>
        <PROPERTY NAME="__type" VALUE=".com.infoblox.dns.bind_ptr"/>
        <PROPERTY NAME="address" VALUE="1.20.168.192.in-addr.arpa"/>
    </OBJECT>
</DATABASE>

我正在尝试弄清楚如何在根目录中搜索具有 NAME __type 和 VALUE .com.infoblox.dns.bind_a 的属性元素,当我找到包含此 NAME 和 VALUE 的对象元素时,我想在字典中保存一些其他名称/值对。

我的最终目标是一本字典,如下所示: {'__type

' : ['.com.infoblox.dns.bind_a','.com.infoblox.dns.bind_a'], 'address' : ['192.168.10.1', '192.168.20.1']}

这是使用以下代码实现的,但也包括 .com.infoblox.dns.bind_ptr __type,现在我想知道是否有人可以帮助我解决仅迭代 PROPERTY 元素所需的逻辑,如果属性__type == .com.infoblox.dns.bind_a,如果是这种情况,则只将所有属性名称/值对放在字典中的该对象下。

import xml.etree.ElementTree as et
from  collections import defaultdict
xml_data = open('onedb.xml').read()
root = et.XML(xml_data)
dict = defaultdict(list)
for child in root:
    for newchild in child:
        property = newchild.get('NAME')
        value = newchild.get('VALUE')
        dict[property].append(value)

所以我现在生成的字典=

print(dict)
defaultdict(<class 'list'>, {'__type': ['.com.infoblox.dns.bind_a', '.com.infoblox.dns.bind_a', '.com.infoblox.dns.bind_ptr'], 'address': ['192.168.10.1', '192.168.20.1', '1.20.168.192.in-addr.arpa']})

我希望它看起来像:

{'__type' : ['.com.infoblox.dns.bind_a','.com.infoblox.dns.bind_a'], 'address' : ['192.168.10.1', '192.168.20.1']}

最终结果将是将数据放入熊猫的数据帧中

如果 XML 文件中OBJECT元素的第一个元素始终是 __type ,则可以在代码中添加几行来实现目标。

import xml.etree.ElementTree as et
from  collections import defaultdict
xml_data = open('onedb.xml').read()
root = et.XML(xml_data)
dict_ = defaultdict(list)
for child in root:
    for i, newchild in enumerate(child):
        property_ = newchild.get('NAME')
        value = newchild.get('VALUE')
        if i == 0 and property_ == '__type' and not value == '.com.infoblox.dns.bind_a':
            break
        dict_[property_].append(value)

我不认为这是最pythonic的解决方案,但它有效。我做了什么?我刚刚child迭代器添加到返回元组enumerate函数中(index of item, item)。这意味着我可以找出迭代器中的哪个项目是第一个。然后我只需检查第一项是否__type并且等于您想要的值。如果没有,我告诉程序使用break关键字for周期内停止迭代。

import xml.etree.ElementTree as ET
import pandas as pd
from collections import defaultdict
data = defaultdict(list)
xml = '''<DATABASE>
    <OBJECT>
        <PROPERTY NAME="__type" VALUE=".com.infoblox.dns.bind_a"/>
        <PROPERTY NAME="address" VALUE="192.168.10.1"/>
    </OBJECT>
    <OBJECT>
        <PROPERTY NAME="__type" VALUE=".com.infoblox.dns.bind_a"/>
        <PROPERTY NAME="address" VALUE="192.168.20.1"/>
    </OBJECT>
    <OBJECT>
        <PROPERTY NAME="__type" VALUE=".com.infoblox.dns.bind_ptr"/>
        <PROPERTY NAME="address" VALUE="1.20.168.192.in-addr.arpa"/>
    </OBJECT>
</DATABASE>'''
root = ET.fromstring(xml)
for obj in root.findall('.//OBJECT'):
    for p in obj.findall('.//PROPERTY'):
        data[p.attrib['NAME']].append(p.attrib['VALUE'])
df = pd.DataFrame(data)
print(df.head())

输出

                        __type                    address
0    .com.infoblox.dns.bind_a               192.168.10.1
1    .com.infoblox.dns.bind_a               192.168.20.1
2  .com.infoblox.dns.bind_ptr  1.20.168.192.in-addr.arpa

相关内容

  • 没有找到相关文章

最新更新