【问题标题】:xml parsing gone wrong, having problem in correct Xpath and loop logicxml 解析出错,正确的 Xpath 和循环逻辑有问题
【发布时间】:2019-09-22 05:46:15
【问题描述】:

我正在使用 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 以及循环逻辑进行更改

【问题讨论】:

  • 你在哪里调用这些函数?
  • @GabrielPellegrino 先生,查看新编辑
  • mainlist 传递给 savetoCSV() 的范围内不存在。将其更改为savetoCSV(newsitems, 'sample.csv')
  • 您从 parseXML 返回并以“newitems”的形式接收返回。但是当你调用 savetoCSV 时,你用“mainlist”来调用它。您需要将 savetoCSV(mainlist, 'sample.csv') 更改为 savetoCSV(newitems, 'sample.csv')
  • @WillardSolutions 和 Gabriel,即使在这样做之后,它也会给出错误:ValueError: dict contains fields not in fieldnames: 'bndbox'

标签: python xpath xml-parsing


【解决方案1】:

我在您的脚本中发现了 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 的快照

【讨论】:

  • 真的非常感谢队友,但我仍然不明白为什么我们使用 if 和 else 条件,你能简单介绍一下吗
猜你喜欢
  • 1970-01-01
  • 2015-07-13
  • 1970-01-01
  • 2014-08-15
  • 2012-02-24
  • 1970-01-01
  • 1970-01-01
  • 2010-10-13
  • 1970-01-01
相关资源
最近更新 更多