将 XML 转换为 CSV

Posted

技术标签:

【中文标题】将 XML 转换为 CSV【英文标题】:Convert XML to CSV 【发布时间】:2013-06-20 04:31:34 【问题描述】:

这是我更新的代码,除了 generate_csv 部分的一件小事外,大部分代码都可以工作。您可以忽略所有 generate_xml 部分。

import os
import sys
import argparse
import csv
import indent
from xml.etree.ElementTree import ElementTree, Element, SubElement, Comment, tostring
import xml.etree.ElementTree as etree

def get_args(args):
    parser = argparse.ArgumentParser(description = "Converts CSV to XML")
    parser.add_argument('-v','--verbose',action='store_true',dest='verbose',help='Increases messages being printed to stdout')
    parser.add_argument("inputfile", help="Please input the name of the CSV file")
    parser.add_argument('-o','--outputfile',help='(optional) Output file name',nargs='?')
    args = parser.parse_args()
    ext = os.path.splitext(args.inputfile)[1].lower()
    if args.outputfile is None:
        if ext == ".csv":
            args.outputfile = os.path.splitext(args.inputfile)[0] + '.xml'

        elif ext == ".xml":
            args.outputfile = os.path.splitext(args.inputfile)[0] + '.csv'

    elif args.outputfile:
        if ext == ".csv":
            outputfile = open(args.outputfile, 'w')
        elif ext == ".xml":
            outputfile = open(args.outputfile,'w')
    else:
        sys.stderr.write('ERROR: Invalid extension %s\n' % ext)
        sys.exit(1)
    return args

def main(argv):
    args = get_args(argv[0:])
    if args is None:
        return 1
    ext = os.path.splitext(args.inputfile)[1].lower()
    if ext == ".csv":
        reader = read_csv(open(args.inputfile))
        generate_xml(reader, args.outputfile)

    if ext == ".xml":
        root = etree.parse(open(args.inputfile)).getroot()
        generate_csv(root, args.outputfile)


    if args.verbose:
        print ('Verbose Selected')
    if args.verbose:
        print ('Convert to XML with set name')

    return 0 

def read_csv(inputfile):
    return list(csv.reader(inputfile))

def generate_xml(reader,outfile):
    root = Element('Solution')
    root.set('version','1.0')
    tree = ElementTree(root)        
    head = SubElement(root, 'DrillHoles')
    description = SubElement(head,'description')
    current_group = None
    i = 0
    for row in reader:
        if i > 0:
            x1,y1,z1,x2,y2,z2,cost = row
            if current_group is None or i != current_group.text:
                current_group = SubElement(description, 'hole','hole_id':"%s"%i)

                collar = SubElement (current_group, 'collar','':', '.join((x1,y1,z1))),
                toe = SubElement (current_group, 'toe','':', '.join((x2,y2,z2)))
                cost = SubElement(current_group, 'cost','':cost)
        i+=1
    head.set('total_holes', '%s'%i)
    indent.indent(root)
    tree.write(outfile)

def generate_csv(root, outfile):

    with open(outfile, 'w') as file_:

        writer = csv.writer(file_, delimiter="\t")

    for a in zip(root.findall("drillholes/hole/collar"),
                 root.findall("drillholes/hole/toe"),
                 root.findall("drillholes/hole/cost")):
        writer.writerow([x.text for x in a])

if (__name__ == "__main__"):
    sys.exit(main(sys.argv))

这是我的新代码,但在 writer.writerow([x.text for x in a]) 处出现错误,提示:I/O operation on a closed file。我该如何解决它

【问题讨论】:

【参考方案1】:
import csv
import sys
import xml.etree.ElementTree as etree

if __name__ == "__main__":

    file_name = sys.argv[1]
    csv_file_name = '.'.join(file_name.split('.')[:-1]) + ".csv"

    root = etree.parse(file_name).getroot()

    with open(csv_file_name, 'w') as file_:

        writer = csv.writer(file_, delimiter="\t")

        for a in zip(root.findall("drillholes/hole/collar"),
                     root.findall("drillholes/hole/toe"),
                     root.findall("drillholes/hole/cost")):
            writer.writerow([x.text for x in a])

【讨论】:

谢谢,如果我想在命令行中提供参数,例如:argparse.py test.xml,如果我在命令行中输入它会给我 test.csv。 然后可以import sys提取文件名,通过sys.argv[1]sys.argv[2]等进行解析。只需将 open(...) 调用中的字符串文字替换为适当的变量即可。 docs.python.org/2/library/sys.html#sys.argv 我在 writer = csv.writer(outfile, delimiter="\t") 处收到错误并说类型错误:参数 1 必须有一个“写入”方法 @Andy 您是否将所有file_ 变量更改为outfile 变量,我几乎可以肯定您遇到的错误是“复制/粘贴”错误。 我必须更改参数,只有其他一切都一样

以上是关于将 XML 转换为 CSV的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python 将 XML 转换为 CSV

将 XML 转换为 CSV

如何编写 XSLT 将 XML 转换为 CSV?

将 CSV 转换为 XML

使用 XSLT 将 XML 转换为 CSV

在python中使用argparse将csv转换为xml