Existe um aplicativo ou biblioteca em Java que me permite converter um CSV
arquivo de dados em XML
arquivo?
As XML
tags seriam fornecidas possivelmente pela primeira linha contendo os cabeçalhos das colunas.
Existe um aplicativo ou biblioteca em Java que me permite converter um CSV
arquivo de dados em XML
arquivo?
As XML
tags seriam fornecidas possivelmente pela primeira linha contendo os cabeçalhos das colunas.
Respostas:
Como os outros acima, não conheço nenhuma maneira simples de fazer isso, mas se você estiver pronto para usar bibliotecas externas muito simples, sugiro:
OpenCsv para análise de CSV (pequeno, simples, confiável e fácil de usar)
Xstream para analisar / serializar XML (muito, muito fácil de usar e criando um xml totalmente legível por humanos)
Usando os mesmos dados de amostra acima, o código ficaria assim:
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();
}
}
}
Produzindo o seguinte resultado: (Xstream permite um ajuste muito fino do resultado ...)
<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>
Eu sei que você pediu Java, mas isso me parece uma tarefa adequada para uma linguagem de script. Aqui está uma solução rápida (muito simples) escrita em 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])
}
}
}
}
Grava o seguinte XML no 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>
No entanto, o código faz uma análise muito simples (sem levar em consideração as vírgulas entre aspas ou com escape) e não leva em consideração a possível ausência de dados.
Eu tenho uma estrutura de código aberto para trabalhar com CSV e arquivos simples em geral. Talvez valha a pena procurar: JFileHelpers .
Com esse kit de ferramentas, você pode escrever código usando beans, como:
@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;
}
e então apenas analise seus arquivos de texto usando:
FileHelperEngine<Customer> engine =
new FileHelperEngine<Customer>(Customer.class);
List<Customer> customers =
new ArrayList<Customer>();
customers = engine.readResource(
"/samples/customers-fixed.txt");
E você terá uma coleção de objetos analisados.
Espero que ajude!
Esta solução não precisa de nenhuma biblioteca CSV ou XML e, eu sei, ela não lida com caracteres ilegais e problemas de codificação, mas você pode estar interessado nela também, desde que sua entrada CSV não quebre as regras mencionadas acima.
Atenção: Você não deve usar este código a menos que saiba o que faz ou não tenha a chance de usar outra biblioteca (possível em alguns projetos burocráticos) ... Use um StringBuffer para ambientes de tempo de execução mais antigos ...
Aqui vamos nos:
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());
A entrada test.csv (roubada de outra resposta desta página):
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
A saída resultante:
<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>
A grande diferença é que o JSefa traz é que ele pode serializar seus objetos java para arquivos CSV / XML / etc e pode desserializar de volta para objetos java. E é impulsionado por anotações que lhe dão muito controle sobre a saída.
JFileHelpers também parece interessante.
Não entendo por que você deseja fazer isso. Soa quase como codificação de culto à carga.
Converter um arquivo CSV em XML não adiciona nenhum valor. Seu programa já está lendo o arquivo CSV, portanto, argumentar que você precisa do XML não funciona.
Por outro lado, ler o arquivo CSV, fazer algo com os valores e, em seguida, serializar para XML faz sentido (bem, tanto quanto usar XML pode fazer sentido ...;)), mas você supostamente já teria um meio de serializando para XML.
Você pode fazer isso de maneira excepcionalmente fácil usando Groovy, e o código é muito legível.
Basicamente, a variável de texto será gravada contacts.xml
para cada linha no contactData.csv
, e a matriz de campos contém cada coluna.
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>"""
}
Você pode usar XSLT . Pesquise no Google e você encontrará alguns exemplos, por exemplo, CSV para XML. Se você usar XSLT, poderá converter o XML para o formato que desejar.
Há também uma boa biblioteca ServingXML de Daniel Parker, que é capaz de converter quase qualquer formato de texto simples para XML e vice-versa.
O exemplo para o seu caso pode ser encontrado aqui : Ele usa o título do campo no arquivo CSV como o nome do elemento XML.
Não há nada que eu conheça que possa fazer isso sem que você, pelo menos, escreva um pouco de código ... Você precisará de 2 bibliotecas separadas:
O analisador CSV que eu recomendaria (a menos que você queira se divertir um pouco para escrever seu próprio analisador CSV) é o OpenCSV (um projeto SourceForge para análise de dados CSV)
O XML Serialization Framework deve ser algo que pode ser escalonado caso você queira transformar um arquivo CSV grande (ou enorme) em XML: Minha recomendação é o Sun Java Streaming XML Parser Framework (veja aqui ), que permite pull-parsing E serialização.
A família de processadores Jackson tem back-ends para vários formatos de dados, não apenas JSON. Isso inclui back-ends XML ( https://github.com/FasterXML/jackson-dataformat-xml ) e CSV ( https://github.com/FasterXML/jackson-dataformat-csv/ ).
A conversão dependeria da leitura de entrada com back-end CSV e da escrita usando back-end XML. Isso é mais fácil de fazer se você tiver (ou puder definir) um POJO para entradas por linha (CSV). Este não é um requisito estrito, pois o conteúdo do CSV também pode ser lido "sem tipo" (uma sequência de String
matrizes), mas requer um pouco mais de trabalho na saída XML.
Para o lado XML, você precisaria de um objeto raiz do wrapper para conter a matriz ou List
de objetos para serializar.
Eu tive o mesmo problema e precisava de um aplicativo para converter um arquivo CSV em um arquivo XML para um de meus projetos, mas não encontrei nada gratuito e bom o suficiente na rede, então codifiquei meu próprio aplicativo Java Swing CSVtoXML.
Está disponível no meu site AQUI . Espero que ajude você.
Se não, você pode facilmente codificar o seu próprio código como eu fiz; O código-fonte está dentro do arquivo jar, portanto, modifique-o conforme necessário, se ele não atender aos seus requisitos.
Para a parte CSV, você pode usar minha pequena biblioteca de código aberto
Isso pode ser uma solução muito básica ou limitada, mas você não poderia fazer um String.split()
em cada linha do arquivo, lembrando a matriz de resultado da primeira linha para gerar o XML, e apenas cuspir os dados da matriz de cada linha com o XML adequado elementos preenchendo cada iteração de um loop?