Convert Deeply Nested XML to CSV in Python
本问题已经有最佳答案,请猛点这里访问。
我不熟悉Python,听说它是解析相当大的XML文件(150MB)的最佳方法之一。我无法理解如何迭代这些标签,只提取
我有一些XML格式如下,我需要使用python从中提取"hw"和"defunit"标记,并将它们转换为.csv格式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <?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> |
我想看到的.csv格式只是:
1 2 | hw, defunit aa, volcanic rock |
以XSLT为例,它是一种XML转换语言,可以将源.xml文件操作到各种最终使用结构,包括.csv等文本文件,并在
python的lxml模块可以运行xslt 1.0脚本。下面假设
XSLT脚本(另存为.xsl,将在下面引用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:ns1="urn:DPS2-metadata" xmlns="urn:COLL"> <xsl:output version="1.0" encoding="UTF-8" indent="yes" method="text"/> <xsl:strip-space elements="*"/> <xsl:template match="/ns1:dps-data/ns1:superentry"> <xsl:text>hw,defunit</xsl:text><xsl:text>
</xsl:text> <xsl:apply-templates select="ns1:entry"/> </xsl:template> <xsl:template match="ns1:entry" namespace="urn:COLL"> <xsl:value-of select="descendant::ns1:hw" namespace="urn:COLL"/><xsl:text>,</xsl:text> <xsl:value-of select="descendant::ns1:defunit" namespace="urn:COLL"/> <xsl:text>
</xsl:text> </xsl:template> |
皮顿脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 |
这个怎么样?
1 2 3 4 5 6 7 8 9 10 | 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} '.format(hw_lst[i].firstChild.data, defu_lst[i].firstChild.data)) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 + ' ') |
如何构建csv文件在很大程度上是基于首选项的,但是我在上面提供了一个简单的例子。如果有多个
编辑:我应该指出,这个特定的实现将整个XML文件读取到内存中。如果您一次只处理一个150MB的文件,这应该不是问题,但这只是需要注意的一点。