lib Java ou aplicativo para converter CSV para arquivo XML?

votos
95

Existe um aplicativo existente ou biblioteca em Java que me permite converter um CSVarquivo de dados para XMLarquivar?

As XMLmarcas seria fornecido por meio de, possivelmente, a primeira fileira contendo cabeçalhos das colunas.

Publicado 01/08/2008 em 17:08
fonte usuário
Em outras línguas...                            


16 respostas

votos
60

Talvez isso pode ajudar: JSefa

Você pode ler o arquivo CSV com esta ferramenta e serializar-lo para XML.

Respondeu 01/08/2008 em 19:51
fonte usuário

votos
45

Como os outros acima, eu não conheço nenhuma maneira de uma etapa para fazer isso, mas se você está pronto para usar bibliotecas externas muito simples, gostaria de sugerir:

OpenCsv para CSV parsing (pequeno, simples, confiável e fácil de usar)

Xstream para analisar / serializar XML (muito, muito fácil de usar, e criar xml legível plenamente humano)

Usando os mesmos dados de exemplo como acima, 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();
        }
    }
}

Produzir o seguinte resultado: (Xstream permite 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>
Respondeu 10/09/2008 em 08:06
fonte usuário

votos
24

Eu sei que você pediu para Java, mas isso me parece uma tarefa bem adequado para uma linguagem de script. Aqui está uma solução rápida (muito simples) escrito 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])
            }
        }
    }
}

Escreve o seguinte XML para 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 muito simples de análise (não tendo em conta citado ou vírgulas escapou) e não leva em conta possíveis dados ausentes.

Respondeu 09/08/2008 em 12:06
fonte usuário

votos
17

Eu tenho uma estrutura de código aberto para trabalhar com CSV e arquivos planos em geral. Talvez vale a pena olhar: JFileHelpers .

Com esse conjunto de ferramentas que você pode escrever código usando feijão, 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 depois é só analisar 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!

Respondeu 28/09/2008 em 00:43
fonte usuário

votos
15

Esta solução não precisa de qualquer CSV ou bibliotecas XML e, eu sei, ele não lidar com quaisquer caracteres ilegais e problemas de codificação, mas você poderia estar interessado nele também, desde a sua entrada CSV não quebrar as regras acima mencionadas.

Atenção: Você não deve usar este código se você não sabe o que você faz ou não tem a chance de usar uma outra biblioteca (possível em alguns projectos burocráticos) ... Use um StringBuffer para ambientes de tempo de execução mais velhos ...

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

O test.csv entrada (roubado de outra resposta sobre esta 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>
Respondeu 22/08/2008 em 00:17
fonte usuário

votos
14

A grande diferença é que JSefa traz é que ele pode serializar seus objetos Java para arquivos CSV / XML / etc e pode anular a serialização de volta para objetos Java. E é impulsionado por anotações que lhe dá grande controle sobre a saída.

JFileHelpers também parece interessante.

Respondeu 11/08/2010 em 06:49
fonte usuário

votos
14

Você pode fazer isso excepcionalmente facilmente usando Groovy, eo código é muito legível.

Basicamente, a variável de texto será escrito para contacts.xmlpara cada linha no contactData.csv, e a matriz contém campos de 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>"""
}
Respondeu 02/10/2008 em 07:08
fonte usuário

votos
13

Eu não entendo por que você iria querer fazer isso. Soa quase como codificação culto à carga.

Convertendo um arquivo CSV para XML não acrescenta qualquer valor. O seu programa já está lendo o arquivo CSV, por isso, argumentando que você precisa XML não funciona.

Por outro lado, a leitura do arquivo CSV, fazendo algo com os valores e, em seguida, a serialização de XML faz sentido (bem, tanto quanto usando XML pode fazer sentido ...;)), mas você teria supostamente já tem um meio de serialização de XML.

Respondeu 01/08/2008 em 20:21
fonte usuário

votos
11

Você pode usar XSLT . Google e você vai encontrar alguns exemplos, por exemplo, CSV para XML Se você usar XSLT você pode, em seguida, converter o XML para qualquer formato desejado.

Respondeu 16/10/2008 em 15:33
fonte usuário

votos
8

Há também boa biblioteca ServingXML por Daniel Parker, que é capaz de converter quase qualquer formato de texto simples para XML e para trás.

O exemplo para o seu caso pode ser encontrada aqui : Ele usa título de campo no arquivo CSV como o nome do elemento XML.

Respondeu 30/09/2008 em 22:22
fonte usuário

votos
7

Não há nada que eu conheço que pode fazer isso sem você, pelo menos, escrever um pouco de código ... Você vai precisar de 2 biblioteca separada:

  • Um quadro CSV Parser
  • Um quadro de serialização XML

O analisador CSV Eu recomendaria (a menos que você quiser ter um pouco de diversão para escrever seu próprio Analisador CSV) é OpenCSV (um projeto SourceForge para analisar dados CSV)

A serialização Framework XML deve ser algo que pode escalar no caso de você querer transformar grande (ou grande) arquivo CSV para XML: Minha recomendação é o Sun Java Transmissão XML Parser Framework (Veja aqui ), que permite puxar-análise e serialização.

Respondeu 04/08/2008 em 02:07
fonte usuário

votos
7

Tanto quanto eu sei, não há nenhuma biblioteca pronta para fazer isso por você, mas produzindo uma ferramenta capaz de traduzir do CSV para XML deve só exigem que você escrever um analisador CSV bruto e ligar JDOM (ou seu XML biblioteca Java de escolha) com um código de cola.

Respondeu 02/08/2008 em 20:06
fonte usuário

votos
4

Jackson família de processadores tem backends para vários formatos de dados, não apenas JSON. Isso inclui tanto XML ( https://github.com/FasterXML/jackson-dataformat-xml ) e CSV ( https://github.com/FasterXML/jackson-dataformat-csv/ backends).

Conversão iria contar com a leitura de entrada com CSV backend, escrever usando backend XML. Isto é mais fácil de fazer se você tem (ou pode definir) um POJO para entradas por-linha (CSV). Esta não é uma exigência estrita, como conteúdo de CSV pode ser lido "sem tipo", bem como (uma sequência de Stringmatrizes), mas exige um trabalho pouco mais na saída XML.

Para o lado XML, você precisaria de um objeto raiz invólucro para conter array ou Listde objetos para serializar.

Respondeu 29/04/2015 em 20:01
fonte usuário

votos
3

Eu tive o mesmo problema e precisava de uma aplicação para converter um arquivo CSV para um arquivo XML para um dos meus projetos, mas não encontrou nada de graça e bom o suficiente na rede, então eu codificadas minha própria aplicação Swing CSVtoXML Java.

Ele está disponível em meu site AQUI . Espero que isso irá ajudá-lo.

Se não, você pode facilmente codificar seu próprio como eu fiz; O código fonte está dentro do arquivo jar tão modificá-lo como você precisa se não preencher sua exigência.

Respondeu 16/04/2014 em 01:12
fonte usuário

votos
3

Para o CSV Part, você pode usar a minha pequena biblioteca de código aberto

Respondeu 16/09/2008 em 17:07
fonte usuário

votos
3

Isso pode ser muito básica ou limitados de uma solução, mas você não poderia fazer um String.split()em cada linha do arquivo, lembrando a matriz resultado da primeira linha para gerar o XML, e apenas cuspir dados da matriz de cada linha com o XML adequada elementos de preenchimento de cada iteração de um loop?

Respondeu 01/08/2008 em 17:31
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more