我现在正在学习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