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

爪哇咖啡中是否有一个现有的应用程序或库,允许我将 CSV数据文件转换为 XML文件?

XML标记可能通过包含列标题的第一行提供。

80069 次浏览

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?

也许这个能帮上忙: JSEFA

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

我不明白你为什么要这么做,这听起来就像货物邪教编码。

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

另一方面,读取 CSV 文件,使用值执行 什么的,然后序列化到 XML 确实有意义(好吧,就像使用 XML 可能有意义一样... ;) ,但是您应该已经有了一种序列化到 XML 的方法。

据我所知,目前还没有现成的库可以为您做到这一点,但是开发一个能够将 CSV 转换为 XML 的工具应该只需要编写一个粗糙的 CSV 解析器,并用一些粘合代码连接 JDOM (或者您选择的 XML Java 库)。

据我所知,如果你不写一点代码的话,没有任何东西可以做到这一点... ... 你将需要两个独立的库:

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

我推荐的 CSV 解析器是 OpenCSV (一个用于解析 CSV 数据的 SourceForge 项目)

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

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.

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 写入标准输出:

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

如上所述,我不知道任何一步到位的方法,但如果您准备使用非常简单的外部库,我建议:

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

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

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

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

我有一个开源框架来处理 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");

并且您将拥有一个已解析对象的集合。

希望能帮上忙!

还有 Daniel Parker 的 服务 XML库,它能够将几乎所有的纯文本格式转换为 XML 并返回。

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

You can do this exceptionally easily using Groovy, and the code is very readable.

基本上,对于 contactData.csv中的每一行,文本变量将写入 contacts.xml,而字段数组包含每一列。

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

你可以使用 XSLT,在谷歌上搜索一下,你会发现一些例子,例如: 如果您使用 XSLT,那么您可以将 XML 转换为您想要的任何格式。

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

JFileHelpers 看起来也很有趣。

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

It's available from my website HERE. Hope it will help you.

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

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