XML到CSV使用xml.etree.ElementTree.interparse功能

2024-10-01 07:37:04 发布

您现在位置:Python中文网/ 问答频道 /正文

各位,我是python的新手(全新的),所以在学习了一门课程之后,我决定创建一个脚本来将XML文件转换成CSV。这个文件的大小是2GB,所以在这里和谷歌上搜索之后,我想我需要使用xml.etree.ElementTree.interparse功能。作为参考,我要转换的XML文件如下所示:

<Document>
  <type></type>
  <internal_id></internal_id>
  <name></name>
  <number></number>
  <cadname></cadname>
  <version></version>
  <iteration></iteration>
  **<isLatest></isLatest>**
  <modifiedBy>
     <username></username>
     <email/>
  </modifiedBy>
  <content>
     **<name></name>**
     <id></id>
     <uploaded></uploaded>
     <refSize></refSize>
     <storage>
        <vault></vault>
        <folder></folder>
        **<filename></filename>**
        <location></location>
        **<actualLocation></actualLocation>**
     </storage>
     <replicatedTo></replicatedTo>
     <copies></copies>
     <status></status>
  </content>

我使用isLatest的值来确定是否需要将项目添加到CSV文件中。如果值是“真”,我希望数据移动到CSV文件。下面是一个有效的代码:

^{pr2}$

如果我运行代码,就会出现以下错误:

Traceback (most recent call last):
  File "C:/Users/mike/PycharmProjects/windchill/xml2csv-stream.py", line 17, in <module>
if document.find('isLatest').text == 'true':
AttributeError: 'NoneType' object has no attribute 'text'

创建的文件包含91000个条目,如下所示:

plate.prt,000000000518e8,/vault/Vlt7
adhesive.prt,0000000005024b,/vault/Vlt7
brd_pad.prt,00000000057862,/vault/Vlt7
support_pad.prt,0000000005024c,/vault/Vlt7
ground.prt,0000000005089b,/vault/Vlt7

输出似乎有两个问题。在

  1. 有些项似乎是重复的,尽管源文件没有重复项。名称可以在源文件中重复,但只能有一个名称值。在
  2. 我认为文件没有完成。我查看了TXT(CSV)文件的最后一个条目,它与源文件的最后一行不匹配。我假设迭代器本质上是串行的。在

所以,你知道错误告诉我什么吗,知道为什么我会看到重复的东西吗?最初我认为这个错误可能与我没有优雅地结束有关。我相信XML在整个过程中都是正确的,但这可能是一个错误的假设。在

******更新*****

这是一个元素的示例。在

<Document>
  <type>wt.epm.EPMDocument</type>
  <internal_id>33709881</internal_id>
  <name>bga_13x11p137_0_4_0_8.prt</name>
  <number>BGA_13X11P137_0_4_0_8.PRT</number>
  <cadname>bga_13x11p137_0_4_0_8.prt</cadname>
  <version>A</version>
  <iteration>1</iteration>
  <isLatest>false</isLatest>
  <modifiedBy>
     <username>ets027 (deleted)</username>
     <email/>
  </modifiedBy>
  <content>
     <name>bga_13x11p137_0_4_0_8.prt</name>
     <id>5341368</id>
     <uploaded>Jan 13, 2006 09:14:41</uploaded>
     <refSize>287764</refSize>
     <storage>
        <vault>master_vault</vault>
        <folder>master_vault7</folder>
        <filename>000000000505a6</filename>
        <location>[wt.fv.FvItem:33709835]::master::master_vault::master_vault7::000000000505a6</location>
        <actualLocation>/vault/Windchill_Vaults/WcVlt7</actualLocation>
     </storage>
     <replicatedTo>
     </replicatedTo>
     <copies>
     </copies>
     <status>Content File Missing</status>
  </content>
</Document>
<Document>
  <type>wt.epm.EPMDocument</type>
  <internal_id>34570129</internal_id>
  <name>d61-2446-02_nest_plate.prt</name>
  <number>D61-2446-02_NEST_PLATE.PRT</number>
  <cadname>d61-2446-02_nest_plate.prt</cadname>
  <version>-</version>
  <iteration>1</iteration>
  <isLatest>true</isLatest>
  <modifiedBy>
     <username>esb044c (deleted)</username>
     <email/>
  </modifiedBy>
  <content>
     <name>d61-2446-02_nest_plate.prt</name>
     <id>5344204</id>
     <uploaded>Jan 30, 2006 09:09:24</uploaded>
     <refSize>109278</refSize>
     <storage>
        <vault>master_vault</vault>
        <folder>master_vault7</folder>
        <filename>000000000518e8</filename>
        <location>[wt.fv.FvItem:34566594]::master::master_vault::master_vault7::000000000518e8</location>
        <actualLocation>/vault/Windchill_Vaults/WcVlt7</actualLocation>
     </storage>
     <replicatedTo>
     </replicatedTo>
     <copies>
     </copies>
     <status>Content File Missing</status>
  </content>
</Document>
<Document>
  <type>wt.epm.EPMDocument</type>
  <internal_id>33512036</internal_id>
  <name>d68-2568-07_press_head_adhesive.prt</name>
  <number>D68-2568-07_PRESS_HEAD_ADHESIVE.PRT</number>
  <cadname>d68-2568-07_press_head_adhesive.prt</cadname>
  <version>-</version>
  <iteration>2</iteration>
  <isLatest>true</isLatest>
  <modifiedBy>
     <username>e3789c (deleted)</username>
     <email/>
  </modifiedBy>
  <content>
     <name>d68-2568-07_press_head_adhesive.prt</name>
     <id>5340927</id>
     <uploaded>Jan 10, 2006 15:42:31</uploaded>
     <refSize>76314</refSize>
     <storage>
        <vault>master_vault</vault>
        <folder>master_vault7</folder>
        <filename>0000000005024b</filename>
        <location>[wt.fv.FvItem:33512072]::master::master_vault::master_vault7::0000000005024b</location>
        <actualLocation>/vault/Windchill_Vaults/WcVlt7</actualLocation>
     </storage>
     <replicatedTo>
     </replicatedTo>
     <copies>
     </copies>
     <status>Content File Missing</status>
  </content>
</Document>
<Document>
  <type>wt.epm.EPMDocument</type>
  <internal_id>34715717</internal_id>
  <name>dbk_flip_sleeve.prt</name>
  <number>DBK_FLIP_SLEEVE.PRT</number>
  <cadname>dbk_flip_sleeve.prt</cadname>
  <version>-</version>
  <iteration>1</iteration>
  <isLatest>false</isLatest>
  <modifiedBy>
     <username>EKA014 (deleted)</username>
     <email/>
  </modifiedBy>
  <content>
     <name>dbk_flip_sleeve.prt</name>
     <id>5344969</id>
     <uploaded>Feb 01, 2006 12:54:43</uploaded>
     <refSize>847210</refSize>
     <storage>
        <vault>master_vault</vault>
        <folder>master_vault7</folder>
        <filename>00000000051b54</filename>
        <location>[wt.fv.FvItem:34714395]::master::master_vault::master_vault7::00000000051b54</location>
        <actualLocation>/vault/Windchill_Vaults/WcVlt7</actualLocation>
     </storage>
     <replicatedTo>
     </replicatedTo>
     <copies>
     </copies>
     <status>Content File Missing</status>
  </content>
 </Document>

以下是我更新的代码:

import xml.etree.ElementTree as ET
import csv

parser = ET.iterparse("windchill.xml", events=('start', 'end'))

csvfile = open('windchill.txt', 'w', encoding="utf-8")

csvwriter = csv.writer(csvfile)

for event, document in parser:

if event=='end' and document.tag=='Document':
    if document.find('type').text == 'wt.epm.EPMDocument' and document.find('isLatest').text == 'true':
        row = []
        version = document.find('version').text
        row.append(version)
        name = document.find('content').find('name').text
        row.append(name)
        filename = document.find('content').find('storage').find('filename').text
        row.append(filename)
#            folder = document.find('content').find('storage').find('actualLocation').text
        folder = document.find('content').find('storage').find('folder').text
        row.append(folder)
        csvwriter.writerow(row)

csvfile.close()

我加了一张打字支票。类型wt.ep.EPM文件会有记录的。然后我想从存储元素中提取数据。特别是名称、文件夹和文件名。我最初使用的是actualallocation,而不是ovvault,但是我改变了主意,希望这个较短的名称可以帮助解决我的内存错误。在


Tags: namemasteridversiontypestoragecontentfolder
1条回答
网友
1楼 · 发布于 2024-10-01 07:37:04

关于您的第一个问题:iterparse在文档中的每个xml元素开始时和关闭时都“看到”。这可能解释了你发现的重复。不仅必须筛选所需的元素,还必须筛选相应的事件。你可以看看这个答案,https://stackoverflow.com/a/46167799/131187,看看如何处理这个问题。在

关于第二个:当document.find('isLatest')找不到您所请求的内容时,它返回None,而不是一个表示xml元素的对象。None没有属性,包括text,因此,您的程序在此时发出嘎嘎声,您将收到一个不完整的csv文件。在


编辑回答注释:此代码解析xml,但不写入csv。csv记录将写入save_csv_record函数或其等效函数中。它只在代码中出现一次,所以应该很容易替换。在

按此代码中的方式调用iterparse只返回“end”事件及其相应的xml元素。因此,代码监视“文档”的“结束”。当它看到一个时,它会询问文档是否包含“isLatest”为“true”。如果它这样做了,它就把它写出来;否则,它忽略它并清空document_content。如果代码没有看到文档的“结尾”,则只需保存标记的内容,并在其下继续读取。在

from xml.etree.ElementTree import iterparse

def save_csv_record(record):
    print(record)
    return

document_content = {}
for ev, el in iterparse('windchill.xml'):
    if el.tag=='Document':
        if document_content['isLatest'] == 'true':
            save_csv_record(document_content)
        document_content = {}
    else:
        document_content[el.tag] = el.text.strip() if el.text else None

输出:

^{pr2}$

为最新代码编辑:

下面是我正在使用的新代码,该代码内存不足:

^{3}$

相关问题 更多 >