在Python中将深度嵌套的XML转换为CSV

在Python中将深度嵌套的XML转换为CSV,python,xml,csv,Python,Xml,Csv,我是Python新手,听说它是解析相当大的XML文件(150MB)的最佳方法之一。我不知道如何遍历标记并只提取和标记,因为它们嵌套得相当深 我有一些XML格式如下,我需要使用Python从中提取“hw”和“defunit”标记,并将它们转换为.csv格式 <?xml version="1.0" encoding="UTF-8"?> <dps-data xmlns="urn:DPS2-metadata" project="SCRABBLELARGE" guid="7d6b7164

我是Python新手,听说它是解析相当大的XML文件(150MB)的最佳方法之一。我不知道如何遍历标记并只提取
标记,因为它们嵌套得相当深

我有一些XML格式如下,我需要使用Python从中提取“hw”和“defunit”标记,并将它们转换为.csv格式

<?xml version="1.0" encoding="UTF-8"?>
<dps-data xmlns="urn:DPS2-metadata" project="SCRABBLELARGE" guid="7d6b7164fde1e064:34368a61:14306b637ab:-8000--4a25ae5c-c104-4c7a-bba5-b434dd4d9314">
    <superentry xmlns="urn:COLL" xmlns:d="urn:COLL" xmlns:e="urn:IDMEE" e:id="u583c10bfdbd326ba.31865a51.12110e76de1.-336">
        <entry publevel="1" id="a000001" e:id="u583c10bfdbd326ba.31865a51.12110e76de1.-335">
            <hwblk>
                <hwgrp>
                    <hwunit>
                        <hw>aa</hw>
                        <ulsrc>edsh</ulsrc>
                    </hwunit>
                </hwgrp>
            </hwblk>
            <datablk>
                <gramcat publevel="1" id="a000001.001">
                    <pospgrp>
                        <pospunit>
                            <posp value="noun" />
                        </pospunit>
                    </pospgrp>
                    <sensecat id="a000001.001.01" publevel="1">
                        <defgrp>
                            <defunit>
                                <def>volcanic rock</def>
                            </defunit>
                        </defgrp>
                    </sensecat>
                </gramcat>
            </datablk>
        </entry>
    </superentry>
  </dps-data>

lxml
库能够进行非常强大的XML解析,并可用于迭代XML树以搜索特定元素

from lxml import etree

with open(r'path/to/xml', 'r') as xml:
    text = xml.read()
tree = lxml.etree.fromstring(text)
row = ['', '']
for item in tree.iter('hw', 'def'):
    if item.tag == 'hw':
       row[0] = item.text
    elif item.tag == 'def':
       row[1] = item.text

line = ','.join(row)

with open(r'path/to/csv', 'a') as csv:
     csv.write(line + '\n')
如何构建CSV文件在很大程度上取决于偏好,但我在上面提供了一个简单的示例。如果有多个
标记,您可以首先提取这些元素(可以使用上面显示的相同
树.iter
方法完成),然后将上述逻辑应用于每个元素


编辑:我应该指出,这个特定的实现将整个XML文件读入内存。如果您一次处理一个150mb的文件,这应该不是问题,但这只是需要注意的。

lxml库能够进行非常强大的XML解析,并可用于在XML树上迭代以搜索特定元素

from lxml import etree

with open(r'path/to/xml', 'r') as xml:
    text = xml.read()
tree = lxml.etree.fromstring(text)
row = ['', '']
for item in tree.iter('hw', 'def'):
    if item.tag == 'hw':
       row[0] = item.text
    elif item.tag == 'def':
       row[1] = item.text

line = ','.join(row)

with open(r'path/to/csv', 'a') as csv:
     csv.write(line + '\n')
如何构建CSV文件在很大程度上取决于偏好,但我在上面提供了一个简单的示例。如果有多个
标记,您可以首先提取这些元素(可以使用上面显示的相同
树.iter
方法完成),然后将上述逻辑应用于每个元素

编辑:我应该指出,这个特定的实现将整个XML文件读入内存。如果您一次只处理一个150mb的文件,这应该不是问题,但这只是需要注意的问题。

这方面如何:

from xml.dom import minidom

xmldoc = minidom.parse('your.xml')
hw_lst = xmldoc.getElementsByTagName('hw')
defu_lst = xmldoc.getElementsByTagName('def')

with open('your.csv', 'a') as out_file:
    for i in range(len(hw_lst)):
        out_file.write('{0}, {1}\n'.format(hw_lst[i].firstChild.data, defu_lst[i].firstChild.data)) 
这个怎么样:

from xml.dom import minidom

xmldoc = minidom.parse('your.xml')
hw_lst = xmldoc.getElementsByTagName('hw')
defu_lst = xmldoc.getElementsByTagName('def')

with open('your.csv', 'a') as out_file:
    for i in range(len(hw_lst)):
        out_file.write('{0}, {1}\n'.format(hw_lst[i].firstChild.data, defu_lst[i].firstChild.data)) 
考虑一下,XML转换语言可以将源.XML文件操作到各种最终使用结构,包括.csv等文本文件,并在
中指定
method=“text”

Python的lxml模块可以运行XSLT1.0脚本。下面假定
标记及其子项使用不同的数据重复。两个未声明的名称空间必须在xsl中处理。此外,XSLT在较小规模的XML上往往非常有效,但因计算机环境而异

XSLT脚本(另存为.xsl,如下所述)

考虑一下,XML转换语言可以将源.XML文件操作到各种最终使用结构,包括.csv等文本文件,并在
中指定
method=“text”

Python的lxml模块可以运行XSLT1.0脚本。下面假定
标记及其子项使用不同的数据重复。两个未声明的名称空间必须在xsl中处理。此外,XSLT在较小规模的XML上往往非常有效,但因计算机环境而异

XSLT脚本(另存为.xsl,如下所述)


重复元素是什么:
?通常,最好先发布XML的前几个重复项,以便我们理解树。@Parfait抱歉,我只被允许编写这么多代码。这是两个重复的元素,是的!重复元素是什么:
?通常,最好先发布XML的前几个重复项,以便我们理解树。@Parfait抱歉,我只被允许编写这么多代码。这是两个重复的元素,是的!此脚本在一定程度上可以正常工作,但在脚本运行时会使我的计算机无法使用。然后我得到了一个ascii错误,但它并没有完成整个文件。谢谢你@Powelllellogram,您的xml文件中有非ascii字符吗?然后你需要相应地处理它们。运行此程序时,您是否检查了计算机冻结的原因?您是否尝试过调试和逐步检查代码以查看可能出现的错误?如果没有,我建议您这样做。此脚本在一定程度上可以正常工作,但在脚本运行时会导致我的计算机无法使用。然后我得到了一个ascii错误,但它并没有完成整个文件。谢谢你@Powelllellogram,您的xml文件中有非ascii字符吗?然后你需要相应地处理它们。运行此程序时,您是否检查了计算机冻结的原因?您是否尝试过调试和逐步检查代码以查看可能出现的错误?如果没有,我建议您这样做。使用此脚本时出现错误“只能将列表(而不是“str”)连接到列表”。我知道我需要将
的值转换为字符串,但不确定如何转换!你能发布完整的错误信息吗?此外,我意识到脚本应该搜索
def
,而不是
defunit
,因为
def
标记包含您想要的文本。
C:\Users\…\Local\Programs\Python\Python 35-32\Python.exe C:/Users/../PycharmProjects/xmltocsv2/xmltocsv.py Traceback(最近一次调用):文件“C:/Users/mbpowell/PycharmProjects/xmltocsv2/xmltocsv.py”,第18行,csv.write(行+'\n')类型错误:只能将列表(而不是“str”)连接到列表中。
是我收到的错误消息。我发现了错误并编辑了代码。问题是,当我调用
'时,'.join(行)
,我没有将结果分配给变量,这意味着生成的字符串从未保存以供以后使用。请改用新的
变量。是的,我也尝试了该变量的修复。然后脚本运行时没有错误,但csv文件没有写入任何内容。我收到错误“只能将列表(而不是“str”)连接到列表”“使用此脚本时。我知道我需要将
的值转换为字符串,但不确定如何转换!你能发布完整的错误信息吗?此外,我意识到脚本应该搜索
def
,而不是
defunit
,因为
def
标记包含tex
import lxml.etree as ET

// LOAD XML AND XSL SOURCES
xml = ET.parse('Input.xml')
xsl = ET.parse('XSLTScript.xsl')

// TRANSFORM SOURCE
transform = ET.XSLT(xsl)
newdom = transform(xml)

// SAVE AS .CSV
with open('Output.csv'), 'wb') as f:
    f.write(newdom)

# hw,defunit
# aa,volcanic rock