Java库或应用程序将CSV转换为XML文件?[关闭]


114

Java中是否有现有的应用程序或库可让我将CSV数据文件转换为XML文件?

XML标签将通过提供可能含有列标题的第一行。


47
看来这是Java中带有SO标签的第一个问题。
Paul Vargas

8
@Paul不仅如此,它也是123!
bjb568 2014年


1
@ bjb568哦。哈哈

4
难怪有史以来第一篇关于Java的Java帖子都被关闭为主题:D
先生。刺猬

Answers:


66

也许这可能会有所帮助:JSefa

您可以使用此工具读取CSV文件并将其序列化为XML。


47

与上面的其他方法一样,我不知道任何一步式的方法,但是如果您准备使用非常简单的外部库,我建议:

OpenCsv用于解析CSV(小巧,简单,可靠且易于使用)

Xstream解析/序列化XML(非常易于使用,并创建完全可读的xml)

使用与上述相同的示例数据,代码如下所示:

package fr.megiste.test;

import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;

import au.com.bytecode.opencsv.CSVReader;

import com.thoughtworks.xstream.XStream;

public class CsvToXml {     

    public static void main(String[] args) {

        String startFile = "./startData.csv";
        String outFile = "./outData.xml";

        try {
            CSVReader reader = new CSVReader(new FileReader(startFile));
            String[] line = null;

            String[] header = reader.readNext();

            List out = new ArrayList();

            while((line = reader.readNext())!=null){
                List<String[]> item = new ArrayList<String[]>();
                    for (int i = 0; i < header.length; i++) {
                    String[] keyVal = new String[2];
                    String string = header[i];
                    String val = line[i];
                    keyVal[0] = string;
                    keyVal[1] = val;
                    item.add(keyVal);
                }
                out.add(item);
            }

            XStream xstream = new XStream();

            xstream.toXML(out, new FileWriter(outFile,false));

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

产生以下结果:(Xstream可以非常精细地调整结果...)

<list>
  <list>
    <string-array>
      <string>string</string>
      <string>hello world</string>
    </string-array>
    <string-array>
      <string>float1</string>
      <string>1.0</string>
    </string-array>
    <string-array>
      <string>float2</string>
      <string>3.3</string>
    </string-array>
    <string-array>
      <string>integer</string>
      <string>4</string>
    </string-array>
  </list>
  <list>
    <string-array>
      <string>string</string>
      <string>goodbye world</string>
    </string-array>
    <string-array>
      <string>float1</string>
      <string>1e9</string>
    </string-array>
    <string-array>
      <string>float2</string>
      <string>-3.3</string>
    </string-array>
    <string-array>
      <string>integer</string>
      <string>45</string>
    </string-array>
  </list>
  <list>
    <string-array>
      <string>string</string>
      <string>hello again</string>
    </string-array>
    <string-array>
      <string>float1</string>
      <string>-1</string>
    </string-array>
    <string-array>
      <string>float2</string>
      <string>23.33</string>
    </string-array>
    <string-array>
      <string>integer</string>
      <string>456</string>
    </string-array>
  </list>
  <list>
    <string-array>
      <string>string</string>
      <string>hello world 3</string>
    </string-array>
    <string-array>
      <string>float1</string>
      <string>1.40</string>
    </string-array>
    <string-array>
      <string>float2</string>
      <string>34.83</string>
    </string-array>
    <string-array>
      <string>integer</string>
      <string>4999</string>
    </string-array>
  </list>
  <list>
    <string-array>
      <string>string</string>
      <string>hello 2 world</string>
    </string-array>
    <string-array>
      <string>float1</string>
      <string>9981.05</string>
    </string-array>
    <string-array>
      <string>float2</string>
      <string>43.33</string>
    </string-array>
    <string-array>
      <string>integer</string>
      <string>444</string>
    </string-array>
  </list>
</list>

27

我知道您要求使用Java,但这令我印象深刻,因为它非常适合脚本语言。这是用Groovy编写的快速(非常简单)的解决方案。

test.csv

string,float1,float2,integer
hello world,1.0,3.3,4
goodbye world,1e9,-3.3,45
hello again,-1,23.33,456
hello world 3,1.40,34.83,4999
hello 2 world,9981.05,43.33,444

csvtoxml.groovy

#!/usr/bin/env groovy

def csvdata = []
new File("test.csv").eachLine { line ->
    csvdata << line.split(',')
}

def headers = csvdata[0]
def dataRows = csvdata[1..-1]

def xml = new groovy.xml.MarkupBuilder()

// write 'root' element
xml.root {
    dataRows.eachWithIndex { dataRow, index ->
        // write 'entry' element with 'id' attribute
        entry(id:index+1) {
            headers.eachWithIndex { heading, i ->
                // write each heading with associated content
                "${heading}"(dataRow[i])
            }
        }
    }
}

将以下XML写入stdout:

<root>
  <entry id='1'>
    <string>hello world</string>
    <float1>1.0</float1>
    <float2>3.3</float2>
    <integer>4</integer>
  </entry>
  <entry id='2'>
    <string>goodbye world</string>
    <float1>1e9</float1>
    <float2>-3.3</float2>
    <integer>45</integer>
  </entry>
  <entry id='3'>
    <string>hello again</string>
    <float1>-1</float1>
    <float2>23.33</float2>
    <integer>456</integer>
  </entry>
  <entry id='4'>
    <string>hello world 3</string>
    <float1>1.40</float1>
    <float2>34.83</float2>
    <integer>4999</integer>
  </entry>
  <entry id='5'>
    <string>hello 2 world</string>
    <float1>9981.05</float1>
    <float2>43.33</float2>
    <integer>444</integer>
  </entry>
</root>

但是,该代码执行非常简单的解析(不考虑带引号或转义的逗号),并且不考虑可能缺少的数据。


因此,您可以调用CSV库进行解析,然后使用标记生成器。也许您可以编辑答案以显示此内容。
Peter Kelley

18

我有一个开放源代码框架,通常可以处理CSV和平面文件。也许值得一看:JFileHelpers

使用该工具箱,您可以使用bean编写代码,例如:

@FixedLengthRecord()
public class Customer {
    @FieldFixedLength(4)
    public Integer custId;

    @FieldAlign(alignMode=AlignMode.Right)
    @FieldFixedLength(20)
    public String name;

    @FieldFixedLength(3)
    public Integer rating;

    @FieldTrim(trimMode=TrimMode.Right)
    @FieldFixedLength(10)
    @FieldConverter(converter = ConverterKind.Date, 
    format = "dd-MM-yyyy")
    public Date addedDate;

    @FieldFixedLength(3)
    @FieldOptional
    public String stockSimbol;  
}

然后使用以下方法解析您的文本文件:

FileHelperEngine<Customer> engine = 
    new FileHelperEngine<Customer>(Customer.class); 
List<Customer> customers = 
    new ArrayList<Customer>();

customers = engine.readResource(
    "/samples/customers-fixed.txt");

并且您将具有一组已解析的对象。

希望有帮助!


+1用于使用注释。不幸的是,到目前为止,该项目自2009-08-11以来似乎没有任何新版本……
Stephan 2012年

是的,从那以后我没有时间继续开发,但是它非常稳定。
kolrie 2012年

17

该解决方案不需要任何CSV或XML库,并且我知道它不会处理任何非法字符和编码问题,但是您也可能对此感兴趣,只要您的CSV输入不违反上述规则。

注意:除非您知道自己的工作或没有机会使用其他库(在某些官僚项目中可能),否则不要使用此代码...为较早的运行时环境使用StringBuffer ...

所以我们开始:

BufferedReader reader = new BufferedReader(new InputStreamReader(
        Csv2Xml.class.getResourceAsStream("test.csv")));
StringBuilder xml = new StringBuilder();
String lineBreak = System.getProperty("line.separator");
String line = null;
List<String> headers = new ArrayList<String>();
boolean isHeader = true;
int count = 0;
int entryCount = 1;
xml.append("<root>");
xml.append(lineBreak);
while ((line = reader.readLine()) != null) {
    StringTokenizer tokenizer = new StringTokenizer(line, ",");
    if (isHeader) {
        isHeader = false;
        while (tokenizer.hasMoreTokens()) {
            headers.add(tokenizer.nextToken());
        }
    } else {
        count = 0;
        xml.append("\t<entry id=\"");
        xml.append(entryCount);
        xml.append("\">");
        xml.append(lineBreak);
        while (tokenizer.hasMoreTokens()) {
            xml.append("\t\t<");
            xml.append(headers.get(count));
            xml.append(">");
            xml.append(tokenizer.nextToken());
            xml.append("</");
            xml.append(headers.get(count));
            xml.append(">");
            xml.append(lineBreak);
            count++;
        }
        xml.append("\t</entry>");
        xml.append(lineBreak);
        entryCount++;
    }
}
xml.append("</root>");
System.out.println(xml.toString());

输入test.csv(从此页面上的另一个答案窃取):

string,float1,float2,integer
hello world,1.0,3.3,4
goodbye world,1e9,-3.3,45
hello again,-1,23.33,456
hello world 3,1.40,34.83,4999
hello 2 world,9981.05,43.33,444

结果输出:

<root>
    <entry id="1">
        <string>hello world</string>
        <float1>1.0</float1>
        <float2>3.3</float2>
        <integer>4</integer>
    </entry>
    <entry id="2">
        <string>goodbye world</string>
        <float1>1e9</float1>
        <float2>-3.3</float2>
        <integer>45</integer>
    </entry>
    <entry id="3">
        <string>hello again</string>
        <float1>-1</float1>
        <float2>23.33</float2>
        <integer>456</integer>
    </entry>
    <entry id="4">
        <string>hello world 3</string>
        <float1>1.40</float1>
        <float2>34.83</float2>
        <integer>4999</integer>
    </entry>
    <entry id="5">
        <string>hello 2 world</string>
        <float1>9981.05</float1>
        <float2>43.33</float2>
        <integer>444</integer>
    </entry>
</root>

15

JSefa带来的最大区别是,它可以将Java对象序列化为CSV / XML / etc文件,并且可以反序列化回Java对象。它由注释驱动,可以使您对输出进行很多控制。

JFileHelpers看起来也很有趣。


14

我不明白您为什么要这么做。听起来几乎像是货物崇拜代码。

将CSV文件转换为XML不会增加任何值。您的程序已经在读取CSV文件,因此认为您需要XML无效。

在另一方面,读取CSV文件,做什么用的值,然后序列化到XML有一定道理(当然,尽可能使用XML能够意义...;)),但你会据说已经拥有的手段序列化为XML。


14

您可以使用Groovy异常轻松地执行此操作,并且代码可读性强。

基本上,将为contacts.xml的每一行写入text变量contactData.csv,并且fields数组包含每一列。

def file1 = new File('c:\\temp\\ContactData.csv')
def file2 = new File('c:\\temp\\contacts.xml')

def reader = new FileReader(file1)
def writer = new FileWriter(file2)

reader.transformLine(writer) { line ->
    fields =  line.split(',')

    text = """<CLIENTS>
    <firstname> ${fields[2]} </firstname>
    <surname> ${fields[1]} </surname>
    <email> ${fields[9]} </email>
    <employeenumber> password </employeenumber>
    <title> ${fields[4]} </title>
    <phone> ${fields[3]} </phone>
    </CLIENTS>"""
}

7
CSV很简单,但是通常永远都不够简单,以至于用逗号分隔就足够了。
艾伦·克鲁格

12

您可以使用XSLT。在Google上搜索,您会找到一些示例,例如CSV到XML 如果使用XSLT,则可以将XML转换为所需的任何格式。


8

还有一个很好的库ServingXMLDaniel Parker,该能够将几乎所有纯文本格式转换为XML,然后转换为XML。

您的案例示例可以在此处找到:它使用CSV文件中的字段标题作为XML元素名称。


7

据我所知,没有您至少无需编写一点点代码就可以做到这一点……您将需要2个单独的库:

  • CSV解析器框架
  • XML序列化框架

我建议的CSV解析器(除非您想自己编写CSV解析器有一点乐趣)是OpenCSV(用于解析CSV数据的SourceForge项目)

XML序列化框架应该是可以扩展的,以防您要将大型(或巨大)CSV文件转换为XML:我的建议是Sun Java Streaming XML Parser框架(请参见此处),该框架允许进行拉式分析和序列化。


7

据我所知,尚无现成的库为您执行此操作,但是要生成能够将CSV转换为XML的工具,只需要编写一个原始的CSV解析器并连接JDOM(或您的XML Java库选择)与一些胶水代码。


4

Jackson处理器系列的后端支持多种数据格式,而不仅仅是JSON。这包括XML(https://github.com/FasterXML/jackson-dataformat-xml)和CSV(https://github.com/FasterXML/jackson-dataformat-csv/)后端。

转换将取决于使用CSV后端读取输入,使用XML后端写入。如果您具有(或可以定义)每行(CSV)条目的POJO,这是最容易做到的。这不是一个严格的要求,因为来自CSV的内容也可以被“无类型”读取(一系列String数组),但是需要更多的XML输出工作。

对于XML,需要包装根对象来包含数组或List要序列化的对象。


3

我遇到了同样的问题,需要一个应用程序将一个项目的CSV文件转换为XML文件,但是在网上找不到任何免费且足够好的东西,所以我编写了自己的Java Swing CSVtoXML应用程序。

这是从我的网站HERE。希望对您有帮助。

如果没有,您可以像我一样轻松地编写自己的代码。源代码位于jar文件中,因此如果它不能满足您的要求,请根据需要进行修改。



3

这可能太基本或仅受解决方案限制,但是您不能String.split()在文件的每一行上执行操作,记住第一行的结果数组以生成XML,然后只将每一行的数组数据吐出正确的XML填充循环的每个迭代的元素?


2
如果您的CSV文件曾经在数据中包含带引号的逗号(不是很常见),则不会。
艾伦·克鲁格
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.