Pergunta

Existe um aplicativo ou biblioteca existente no Java o que me permitirá converter um CSV arquivo de dados para XML arquivo?

O XML as tags seriam fornecidas possivelmente através da primeira linha contendo cabeçalhos de coluna.

Foi útil?

Solução

Talvez isso possa ajudar: JSefa

Você pode ler o arquivo CSV com esta ferramenta e serializá-lo em XML.

Outras dicas

Como os outros acima, não conheço nenhuma maneira de fazer isso em uma única etapa, mas se você estiver pronto para usar bibliotecas externas muito simples, sugiro:

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

Stream X analisar/serializar XML (muito, muito fácil de usar e criar xml totalmente legível por humanos)

Usando os mesmos dados de exemplo 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 preciso 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.

teste.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 em 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 conta as vírgulas entre aspas ou com escape) e não leva em conta possíveis dados ausentes.

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 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, não lida com caracteres ilegais e problemas de codificação, mas você também pode estar interessado nela, desde que sua entrada CSV não viole 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 oportunidade 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 nesta 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 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 oferecem muito controle sobre a saída.

JFileHelpers também parece interessante.

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

Converter um arquivo CSV em XML não agrega nenhum valor.Seu programa já está lendo o arquivo CSV, então argumentar que você precisa de XML não funciona.

Por outro lado, lendo o arquivo CSV, fazendo algo com os valores, e então serializar para XML faz sentido (bem, tanto quanto usar XML pode fazer sentido...;)) mas você supostamente já teria um meio de serializar para XML.

Você pode fazer isso com muita facilidade usando o Groovy, e o código é muito legível.

Basicamente, a variável de texto será escrita em contacts.xml para cada linha do 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ê poderia usar XSLT.Pesquise no Google e você encontrará alguns exemplos, por ex. CSV para XMLSe você usar XSLT você pode então converter o XML para qualquer formato que desejar.

Há também uma boa biblioteca ServindoXML 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 cabeçalho do campo no arquivo CSV como o nome do elemento XML.

Não há nada que eu saiba que possa fazer isso sem que você pelo menos escreva um pouco de código...Você precisará de 2 bibliotecas separadas:

  • Uma estrutura de analisador CSV
  • Uma estrutura de serialização XML

O analisador CSV que eu recomendaria (a menos que você queira se divertir um pouco escrevendo seu próprio analisador CSV) é OpenCSV (um projeto SourceForge para análise de dados CSV)

O XML Serialization Framework deve ser algo que possa 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 análise pull E serialização.

Até onde eu sei, não existe uma biblioteca pronta para fazer isso para você, mas produzir uma ferramenta capaz de traduzir de CSV para XML deve exigir apenas que você escreva um analisador CSV bruto e conecte o JDOM (ou sua biblioteca XML Java de escolha) com algum código de cola.

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

A conversão dependeria da leitura da entrada com back-end CSV e da gravação 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 como "não digitado" (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 wrapper para conter array ou List de objetos a serem serializados.

Isso pode ser uma solução muito básica ou limitada, mas você não poderia fazer uma String.split() em cada linha do arquivo, lembrando-se da matriz de resultados da primeira linha para gerar o XML e apenas cuspindo os dados da matriz de cada linha com os elementos XML adequados preenchendo cada iteração de um loop?

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 isso ajude você.

Caso contrário, você pode facilmente codificar o seu próprio como eu fiz;O código-fonte está dentro do arquivo jar, então 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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top