将 CSV 转换为 XML 文件的 Java 库或应用程序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/123/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 23:30:35  来源:igfitidea点击:

Java lib or app to convert CSV to XML file?

javaxmlcsvdata-conversion

提问by A Salim

Is there an existing application or library in Javawhich will allow me to convert a CSVdata file to XMLfile?

Java中是否存在允许我将CSV数据文件转换为文件的现有应用程序或库XML

The XMLtags would be provided through possibly the first row containing column headings.

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

采纳答案by svrist

Maybe this might help: JSefa

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

You can read CSV file with this tool and serialize it to XML.

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

回答by saint_groceon

This may be too basic or limited of a solution, but couldn't you do a String.split()on each line of the file, remembering the result array of the first line to generate the XML, and just spit each line's array data out with the proper XML elements padding each iteration of a loop?

这可能太基本或有限的解决方案,但你不能String.split()在文件的每一行上做一个,记住第一行的结果数组来生成 XML,然后用正确的 XML 吐出每一行的数组数据填充循环的每次迭代的元素?

回答by Ryan Fox

I don't understand why you would want to do this. It sounds almost like cargo cult coding.

我不明白你为什么要这样做。这听起来几乎就像货物崇拜编码。

Converting a CSV file to XML doesn't add any value. Your program is already reading the CSV file, so arguing that you need XML doesn't work.

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

On the other hand, reading the CSV file, doing somethingwith the values, and then serializing to XML does make sense (well, as much as using XML can make sense... ;)) but you would supposedly already have a means of serializing to XML.

另一方面,读取 CSV 文件,对值做一些事情,然后序列化为 XML 确实有意义(嗯,就像使用 XML 一样有意义......;))但你应该已经有了一种方法序列化为 XML。

回答by Matt

As far as I know, there's no ready-made library to do this for you, but producing a tool capable of translating from CSV to XML should only require you to write a crude CSV parser and hook up JDOM (or your XML Java library of choice) with some glue code.

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

回答by Claude Houle

There is nothing I know of that can do this without you at least writing a little bit of code... You will need 2 separate library:

如果没有您至少编写一点代码,我不知道可以做到这一点......您将需要 2 个单独的库:

  • A CSV Parser Framework
  • An XML Serialization Framework
  • CSV 解析器框架
  • XML 序列化框架

The CSV parser I would recommend (unless you want to have a little bit of fun to write your own CSV Parser) is OpenCSV (A SourceForge Project for parsing CSV Data)

我推荐的 CSV 解析器(除非你想有一点乐趣来编写自己的 CSV 解析器)是 OpenCSV(一个用于解析 CSV 数据的 SourceForge 项目)

The XML Serialization Framework should be something that can scale in case you want to transform large (or huge) CSV file to XML: My recommendation is the Sun Java Streaming XML Parser Framework (See here) which allows pull-parsing AND serialization.

XML Serialization Framework 应该是可以扩展的,以防您想将大型(或巨大)CSV 文件转换为 XML:我的建议是 Sun Java Streaming XML Parser Framework(请参阅此处),它允许拉解析和序列化。

回答by Anthony Cramp

I know you asked for Java, but this strikes me as a task well suited to a scripting language. Here is a quick (very simple) solution written in Groovy.

我知道您要求使用 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

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])
            }
        }
    }
}

Writes the following XML to stdout:

将以下 XML 写入标准输出:

<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>

However, the code does very simple parsing (not taking into account quoted or escaped commas) and it does not account for possible absent data.

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

回答by Martin Klinke

This solution does not need any CSV or XML libraries and, I know, it does not handle any illegal characters and encoding issues, but you might be interested in it as well, provided your CSV input does not break the above mentioned rules.

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

Attention:You should not use this code unless you know what you do or don't have the chance to use a further library (possible in some bureaucratic projects)... Use a StringBuffer for older Runtime Environments...

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

So here we go:

所以我们开始:

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());

The input test.csv (stolen from another answer on this page):

输入 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

The resulting output:

结果输出:

<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>

回答by Laurent K

As the others above, I don't know any one-step way to do that, but if you are ready to use very simple external libraries, I would suggest:

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

OpenCsvfor parsing CSV (small, simple, reliable and easy to use)

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

Xstreamto parse/serialize XML (very very easy to use, and creating fully human readable xml)

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

Using the same sample data as above, code would look like:

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

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();
        }
    }
}

Producing the following result: (Xstream allows very fine tuning of the result...)

产生以下结果:(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>

回答by Arne Burmeister

For the CSV Part, you may use my little open source library

对于 CSV 部分,您可以使用我的小开源库

回答by kolrie

I have an opensource framework for working with CSV and flat files in general. Maybe it's worth looking: JFileHelpers.

我有一个用于处理 CSV 和平面文件的开源框架。也许值得一看:JFileHelpers

With that toolkit you can write code using beans, like:

使用该工具包,您可以使用 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;  
}

and then just parse your text files using:

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

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

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

And you'll have a collection of parsed objects.

您将拥有一组已解析的对象。

Hope that helps!

希望有帮助!