我正在使用ElementTree xml API将保存在目录中的本地XML文件中的某些数据转换为CSV文件,该XML文件如下所示
<object>
<name>Eosinophil</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>415</xmin>
<ymin>120</ymin>
<xmax>532</xmax>
<ymax>252</ymax>
</bndbox>
</object>
我正在尝试使用以下python代码来做到这一点:
def parseXML(xmlfile):
tree = ET.parse(xmlfile)
root = tree.getroot()
mainlist = []
for object in root.findall('.//object'):
records = {}
for bndbox in object:
records[bndbox.tag] = bndbox.text.encode('utf8')
mainlist.append(records)
return mainlist
def savetoCSV(newsitems, filename):
fields = ['name', 'pose', 'truncated', 'difficult', 'xmin','ymin', 'xmax','ymax']
with open(filename, 'w') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames = fields)
writer.writeheader()
writer.writerows(newsitems)
没有给出任何错误,但它只是创建了具有适当标题的空CSV文件,因为我不熟悉这些东西,因此我搜索了资源,并且我认为“ root.findall中的对象”循环存在问题,请提供帮助这种情况。
我正在按以下方式调用这些函数
def main():
newsitems = parseXML('My photo - 09-04-2019_10-11-32.xml')
savetoCSV(mainlist, 'sample.csv')
您能否建议循环中涉及的Xpath更改以及循环逻辑
答案 0 :(得分:0)
我在您的脚本中看到2个问题。
1)您不应将bndbox
用作for循环对象,因为存在一个具有该名称的节点
2)当获得具有子节点的名称bndbox
时,应遍历子节点以获取信息。
这是您问题的解决方案。 (经过测试并按预期工作)
import xml.etree.ElementTree as ET
import csv
def parseXML(xmlfile):
tree = ET.parse(xmlfile)
root = tree.getroot()
mainlist = []
for object in root.findall('.//object'):
records = {}
for node in object:
if (len(node.findall("*"))>0):
for subnode in node.findall('*'):
records[subnode.tag] = subnode.text.encode('utf8')
else:
records[node.tag] = node.text.encode('utf8')
mainlist.append(records)
print(mainlist)
return mainlist
def savetoCSV(newsitems, filename):
fields = ['name', 'pose', 'truncated', 'difficult', 'xmin','ymin', 'xmax','ymax']
with open(filename, 'w') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames = fields)
writer.writeheader()
writer.writerows(newsitems)
xmlfile = r"C:\Users\supputuri\PycharmProjects\Selenium_Test\Data\emps.xml"
items = parseXML(xmlfile)
savetoCSV(items,"output.csv")
我刚刚添加了第二个对象集,以确保脚本可以在多个集上正常工作。这是output.csv的快照 {{3}}