【发布时间】:2017-03-15 02:21:05
【问题描述】:
我刚开始研究使用 python 从 csv 生成 XML。我正在尝试使用 ElementTree 来做到这一点。但是,我无法获得我想要的格式。
Here 是我正在使用的示例 csv 数据。原始数据大约有 1200 万行,由此产生的完整 xml 将有大约 3800 万行。下面是我的代码。
import csv
import sys
from xml.etree.ElementTree import Element, SubElement, Comment, ElementTree, tostring
from xml.etree import ElementTree
from xml.dom import minidom
def prettify(elem):
rough_string = tostring(elem, 'utf-8', method="xml")
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent=" ")
root = Element('plans')
sys.stdout = open('C:/Users/s/Desktop/xml6.xml', 'w')
print(prettify(root))
with open('C:/Users/s/Desktop/trip2.csv', 'rt') as f:
current_group = None
reader = csv.reader(f)
for row in reader:
personid, hno, pno, OXutmmtr, OYutmmtr, DXutmmtr, DYutmmtr, opcl, dpcl, depday, deptm, arrtm, newendacttma, dept, arr, newendacttmh, mode2, opurp2, dpurp2, dorp2 = row
if current_group is None or personid != old1 :
# Start a new group
current_group = SubElement(root, 'person', {'id':personid})
old1 = personid
pln = SubElement(current_group, 'plan')
activ = SubElement(pln, 'act', {'type':opurp2, 'x':OXutmmtr, 'y':OYutmmtr,})
trvl = SubElement(pln, 'leg', {'mode': mode2,})
activ = SubElement(pln, 'act',{'type': dpurp2, 'x': DXutmmtr, 'y': DYutmmtr,})
elif personid == old1:
trvl = SubElement(pln, 'leg', {'mode': mode2,})
activ = SubElement(pln, 'act', {'type': dpurp2, 'x': DXutmmtr,'y': DYutmmtr,})
if newendacttmh == "02:59:00":
sys.stdout = open('C:/Users/s/Desktop/xml6.xml', 'a')
print(prettify(current_group))
root.clear()
我需要像
这样的格式<?xml version="1.0" ?>
<plans>
<person id="101">
<plan>
<act type="home" x="338471.624256" y="3114225.84531"/>
<leg mode="sov"/>
<act type="work" x="353108.46905" y="3086263.42028"/>
<leg mode="sov"/>
<act type="home" x="338471.624256" y="3114225.84531"/>
</plan>
</person>
<person id="201">
<plan>
<act type="home" x="338535.623855" y="3114558.14898"/>
<leg mode="hov3+"/>
<act type="meal" x="338520.432083" y="3105225.60283"/>
<leg mode="hov3+"/>
<act type="shop" x="333193.19769" y="3103842.61842"/>
<leg mode="hov3+"/>
<act type="pers.bus" x="338148.26292" y="3083556.85073"/>
<leg mode="hov3+"/>
<act type="home" x="338535.623855" y="3114558.14898"/>
</plan>
</person>
</plans>
但我得到的格式类似于
<?xml version="1.0" ?>
<plans/>
<?xml version="1.0" ?>
<person id="101">
<plan>
<act type="home" x="338471.624256" y="3114225.84531"/>
<leg mode="sov"/>
<act type="work" x="353108.46905" y="3086263.42028"/>
<leg mode="sov"/>
<act type="home" x="338471.624256" y="3114225.84531"/>
</plan>
</person>
<?xml version="1.0" ?>
<person id="201">
<plan>
<act type="home" x="338535.623855" y="3114558.14898"/>
<leg mode="hov3+"/>
<act type="meal" x="338520.432083" y="3105225.60283"/>
<leg mode="hov3+"/>
<act type="shop" x="333193.19769" y="3103842.61842"/>
<leg mode="hov3+"/>
<act type="pers.bus" x="338148.26292" y="3083556.85073"/>
<leg mode="hov3+"/>
<act type="home" x="338535.623855" y="3114558.14898"/>
</plan>
</person>
本质上,当我到达每个人的记录末尾时(由时间字符串 02:59:00 指示),我试图追加到文件,因为如果我等到整个根树构建完成,那么我就会遇到内存错误问题。有趣的是,内存使用量永远不会超过 2 gb,即使还剩下 12 gb 的内存,程序也会因内存错误问题而失败。我已尝试遵循 here 关于使用 ElementTree(top).write(sys.stdout) 序列化 xml-stream 的建议,但无法操作它。我知道(有点)SAX 解析器更适合创建大型 xml。但是,此刻我有点被它吓倒了。任何建议或意见都会对我有用。
【问题讨论】:
-
我看不出你的两个 XML 示例有什么区别。您只是在谈论空格的区别吗?
-
在第一个(也是正确的)版本中,所有
person元素都在plans元素内。在第二个版本中,plans元素在第二行开始和结束,person元素独立于plans。此外,在第二个版本中,xml 前导码<?xml version="1.0" ?>对每个person元素重复。 -
你为什么要以这种奇怪的方式做事,使用
tostring输出XML,然后用minidom再次读取它? -
据说,元素树不会缩进 xml 输出。所以,美化功能就是这样做的。但更重要的是,我完全是 python 新手,我正在重新利用我从 here 获得的代码,所以对这段代码没有完整的了解。
标签: python xml csv elementtree