将CSV转换为XML

3
我目前正在尝试为水文模型(HBV-light)制作输入文件,使其与外部校准软件(PEST)兼容。HBV-light要求其输入文件为XML格式,而PEST只能读取文本文件。我的问题涉及编写一个脚本,自动将由PEST编写的参数集(CSV格式)转换为可以被HBV-light读取的XML文件。
这是PEST可以编写的文本文件的简短示例:
W,X,Y,Z
1,2,3,4

以下是我试图组织XML文件的方式:

<Parameters>
   <GroupA>
      <W>1</W>
      <X>2</X>
   </GroupA>
   <GroupB>
      <Y>3</Y>
      <Z>4</Z>
   </GroupB>
</Parameters>

我没有编程经验,但这是我编写的Python代码:

我完全没有编程经验,但是这是我迄今为止编写的Python代码:

import csv

csvFile = 'myCSVfile.csv'
xmlFile = 'myXMLfile.xml'

csvData = csv.reader(open(csvFile))
xmlData = open(xmlFile, 'w')
xmlData.write('<?xml version="1.0" encoding="utf-8"?>' + "\n")
# there must be only one top-level tag
xmlData.write('<Catchment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">' + "\n")
xmlData.write('<CatchmentParamters>' + "\n")
rowNum = 0
for row in csvData:
    if rowNum == 0:
        tags = row
        # replace spaces w/ underscores in tag names
        for i in range(0, 2):
            tags[i] = tags[i].replace(' ', '_')
    else: 
        for i in range(0, 2):
            xmlData.write('    ' + '<' + tags[i] + '>' \
                          + row[i] + '</' + tags[i] + '>' + "\n")

    rowNum +=1

xmlData.write('</CatchmentParameters>' + "\n")
xmlData.write('<VegetationZone>' + "\n")
xmlData.write('<VegetationZoneParameters>' + "\n")
rowNum = 0
for row in csvData:
    if rowNum == 0:
        tags = row
        # replace spaces w/ underscores in tag names
        for i in range(3, 5):
            tags[i] = tags[i].replace(' ', '_')
    else: 
        for i in range(3, 5):
            xmlData.write('    ' + '<' + tags[i] + '>' \
                          + row[i] + '</' + tags[i] + '>' + "\n")

    rowNum +=1

xmlData.write('</VegetationZoneParameters>' + "\n")
xmlData.write('</VegetationZone>' + "\n")
xmlData.write('</Catchment>' + "\n")
xmlData.close()

我可以将A组(或特别是CathmentParameters)写入,但B组部分未被写入。不确定该怎么办!


1
作为“第一次提问”的问题,这个写得非常好!我没有一个快速的答案给你 - 但是请看一下https://dev59.com/73A65IYBdhLWcg3w1SXU - Floris
我确实对你的回答有些慢...请看下面。 - Floris
将来你可能需要考虑的一件事是 - 你的代码似乎处理了两次文件,就好像你想要所有集水区参数在任何植被参数之前 - 这就是我写答案的方式。从被接受的答案来看,你打算做些不同的事情。一个包含两行数据的示例将显示差异。请记住,帮助SO的人无法读取思维 - 他们只能从您提供的信息进行推断。 - Floris
3个回答

1
我认为循环有问题。尝试一下这个方法,看看是否可行。
#! /usr/bin/env python
# coding= utf-8

import csv

csvFile = 'myCSVfile.csv'
xmlFile = 'myXMLfile.xml'

csvData = csv.reader(open(csvFile))
xmlData = open(xmlFile, 'w')
xmlData.write('<?xml version="1.0" encoding="utf-8"?>' + "\n")
# there must be only one top-level tag
xmlData.write('<Catchment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">' + "\n")
xmlData.write('<CatchmentParamters>' + "\n")
rowNum = 0


for row in csvData:
    if rowNum == 0:
        tags = row
        # replace spaces w/ underscores in tag names
        for i in range(0, 2):
            tags[i] = tags[i].replace(' ', '_')

    else: 
      for i in range(0, 2):
            xmlData.write('    ' + '<' + tags[i] + '>' \
                          + row[i] + '</' + tags[i] + '>' + "\n")

      xmlData.write('</CatchmentParameters>' + "\n")
      xmlData.write('<VegetationZone>' + "\n")
      xmlData.write('<VegetationZoneParameters>' + "\n")

      for i in range(2, 4):
            xmlData.write('    ' + '<' + tags[i] + '>' \
                          + row[i] + '</' + tags[i] + '>' + "\n")

      xmlData.write('</VegetationZoneParameters>' + "\n")
      xmlData.write('</VegetationZone>' + "\n")

    rowNum +=1

xmlData.write('</Catchment>' + "\n")
xmlData.close()

非常感谢你在解决我的问题时的研究!! 这是解决我遇到的问题的好方法。我仍然是一个极端的编程新手,所以仍在学习循环的工作方式,你修改我的代码的方式让我明白了问题出在哪里! - Geogrammer
我猜你发现了你的第一个标签 CatchmentParamters 拼错了。 - Floris

1
问题在于你对csv文件的内容进行了两次迭代 - 似乎你需要在第一次循环后“倒回”文件。还有一个小的索引问题,在第二个范围中需要使用range(2,4)而不是已经指出的range(3,5)
我创建了一段代码,它似乎可以工作。可能有人能够更好地理解Python并对其进行改进。注意 - 我添加了几个打印语句以确信自己理解发生了什么。如果你不第二次打开csvFile(在“开始第二个for循环”处),那么没有任何行被打印。这是问题所在的线索。
import csv

csvFile = 'myCSVfile.csv'
xmlFile = 'myXMLfile.xml'

csvData = csv.reader(open(csvFile))
xmlData = open(xmlFile, 'w')
xmlData.write('<?xml version="1.0" encoding="utf-8"?>' + "\n")
# there must be only one top-level tag
xmlData.write('<Catchment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">' + "\n")
xmlData.write('<CatchmentParamters>' + "\n")
rowNum = 0
for row in csvData:
    print "row is ", row
    if rowNum == 0:
        tags = row
        # replace spaces w/ underscores in tag names
        for i in range(0, 2):
            tags[i] = tags[i].replace(' ', '_')
    else: 
        for i in range(0, 2):
            xmlData.write('    ' + '<' + tags[i] + '>' \
                          + row[i] + '</' + tags[i] + '>' + "\n")

    rowNum +=1

xmlData.write('</CatchmentParameters>' + "\n")
xmlData.write('<VegetationZone>' + "\n")
xmlData.write('<VegetationZoneParameters>' + "\n")
rowNum = 0
print "starting the second for loop"
csvData = csv.reader(open(csvFile))
for row in csvData:
    print "row is now ", row
    if rowNum == 0:
        tags = row
        # replace spaces w/ underscores in tag names
        for i in range(2, 4):
            tags[i] = tags[i].replace(' ', '_')
    else: 
        for i in range(2, 4):
            xmlData.write('    ' + '<' + tags[i] + '>' \
                          + row[i] + '</' + tags[i] + '>' + "\n")

    rowNum +=1

xmlData.write('</VegetationZoneParameters>' + "\n")
xmlData.write('</VegetationZone>' + "\n")
xmlData.write('</Catchment>' + "\n")
xmlData.close()

使用上面的内容和你提供的小测试文件,生成了以下XML文件:
<?xml version="1.0" encoding="utf-8"?>
<Catchment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CatchmentParamters>
    <W>1</W>
    <X>2</X>
</CatchmentParameters>
<VegetationZone>
<VegetationZoneParameters>
    <Y>3</Y>
    <Z>4</Z>
</VegetationZoneParameters>
</VegetationZone>
</Catchment>

问题解决了吗?

是的!非常感谢你抽出时间来尝试一下!看起来有(至少)两种简单的方法可以解决这个问题。我对循环还不太熟悉,所以问题出在那里也说得通。 - Geogrammer
很高兴你找到了解决方案! - Floris

1

我认为问题在于你第二部分的范围定义... range(3, 5) 意味着元素4和5,你想要的可能是 range(2,4) 意味着元素3和4。


当然。我还在适应索引。谢谢! - Geogrammer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接