在Python中将深度嵌套的XML转换为CSV
我是Python新手,听说它是解析相当大的XML文件(150MB)的最佳方法之一。我不知道如何遍历标记并只提取在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
和
标记,因为它们嵌套得相当深
我有一些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