Java lib o aplicación para convertir CSV a archivo XML?


¿Hay una aplicación o biblioteca existente en Java que me permita convertir un archivo de datos CSV en un archivo XML?

Las etiquetas XML se proporcionarían posiblemente a través de la primera fila que contiene encabezados de columna.

Author: Mohit, 2008-08-01

16 answers

Tal vez esto podría ayudar: JSefa

Puede leer el archivo CSV con esta herramienta y serializarlo a XML.

 62
Author: svrist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-07 10:36:04

Al igual que los anteriores, no conozco ninguna forma de hacerlo en un solo paso, pero si está listo para usar bibliotecas externas muy simples, le sugeriría:

OpenCSV para analizar CSV (pequeño, simple, confiable y fácil de usar)

Xstream para analizar / serializar XML (muy, muy fácil de usar, y crear xml completamente legible por humanos)

Usando los mismos datos de muestra que los anteriores, el código se vería como:

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

Produciendo el siguiente resultado: (Xstream permite muy bien afinación del 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>
 46
Author: Laurent K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-27 06:06:59

Sé que pediste Java, pero esto me parece una tarea muy adecuada para un lenguaje de scripting. Aquí hay una solución rápida (muy simple) escrita en Groovy.

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

Escribe el siguiente XML en 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>

Sin embargo, el código hace un análisis muy simple (sin tener en cuenta las comas citadas o escapadas) y no tiene en cuenta los posibles datos ausentes.

 25
Author: Anthony Cramp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-07 10:37:12

Tengo un framework opensource para trabajar con CSV y archivos planos en general. Tal vez vale la pena mirar: JFileHelpers.

Con ese kit de herramientas puedes escribir 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;  
}

Y luego simplemente analiza tus archivos de texto usando:

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

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

Y tendrás una colección de objetos analizados.

¡Espero que eso ayude!

 18
Author: kolrie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-07 18:56:09

Esta solución no necesita bibliotecas CSV o XML y, lo sé, no maneja caracteres ilegales y problemas de codificación, pero también podría interesarle, siempre que su entrada CSV no rompa las reglas mencionadas anteriormente.

Atención: No debe usar este código a menos que sepa lo que hace o no tiene la oportunidad de usar una biblioteca adicional (posible en algunos proyectos burocráticos)... Utilice un StringBuffer para entornos de tiempo de ejecución más antiguos...

So aquí vamos:

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

La prueba de entrada.csv (robado de otra respuesta en 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

La salida 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>
 17
Author: Martin Klinke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-02 14:14:39

No entiendo por qué querrías hacer esto. Suena casi como codificación de culto de carga.

Convertir un archivo CSV a XML no añade ningún valor. Su programa ya está leyendo el archivo CSV, por lo que argumentar que necesita XML no funciona.

Por otro lado, leer el archivo CSV, hacer algo con los valores, y luego serializar a XML tiene sentido (bueno, tanto como usar XML puede tener sentido... ;)) pero supuestamente ya tendría un medio de serialización a XML.

 15
Author: Ryan Fox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-01 19:21:57

La gran diferencia es que JSefa aporta es que puede serializar sus objetos java a archivos CSV/XML/etc y puede deserializar de nuevo a objetos java. Y es impulsado por anotaciones que le da mucho control sobre la salida.

JFileHelpers también parece interesante.

 15
Author: James Selvakumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-07 10:40:32

Puede hacer esto excepcionalmente fácilmente usando Groovy, y el código es muy legible.

Básicamente, la variable text se escribirá en contacts.xml para cada línea en el contactData.csv, y el array fields contiene cada columna.

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>"""
}
 15
Author: abarax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-10 20:04:49

Puedes usar XSLT. Google y encontrará algunos ejemplos, por ejemplo, CSV a XML Si utiliza XSLT puede convertir el XML al formato que desee.

 12
Author: Simmo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-07 10:41:10

También hay una buena biblioteca ServingXML de Daniel Parker, que es capaz de convertir casi cualquier formato de texto plano a XML y viceversa.

El ejemplo para su caso se puede encontrar aquí: Utiliza el encabezado del campo en el archivo CSV como el nombre del elemento XML.

 8
Author: Lukáš Rampa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-07 10:45:43

Por lo que sé, no hay una biblioteca preparada para hacer esto por usted, pero producir una herramienta capaz de traducir de CSV a XML solo debería requerir que escriba un analizador CSV crudo y conecte JDOM (o su biblioteca XML Java de su elección) con algún código de pegamento.

 8
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-10 20:56:11

No hay nada que sepa que pueda hacer esto sin que al menos escribas un poco de código... Necesitará 2 bibliotecas separadas:

  • Un marco de análisis CSV
  • Un Framework de Serialización XML

El analizador CSV que recomendaría (a menos que quiera divertirse un poco para escribir su propio analizador CSV) es OpenCSV (Un proyecto de SourceForge para analizar Datos CSV)

El marco de serialización XML debe ser algo que pueda escalar en caso de que desee transformar archivo CSV grande (o enorme) a XML: Mi recomendación es el marco de análisis XML de Sun Java Streaming (Ver aquí) que permite el análisis por pull Y la serialización.

 7
Author: Claude Houle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-26 00:02:54

Esto puede ser demasiado básico o limitado de una solución, pero no podría hacer un String.split() en cada línea del archivo, recordando la matriz de resultados de la primera línea para generar el XML, y simplemente escupir los datos de la matriz de cada línea con los elementos XML adecuados relleno cada iteración de un bucle?

 4
Author: saint_groceon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-26 00:02:16

La familia de procesadores Jackson tiene backends para múltiples formatos de datos, no solo JSON. Esto incluye tanto XML ( https://github.com/FasterXML/jackson-dataformat-xml ) y CSV ( https://github.com/FasterXML/jackson-dataformat-csv / ) motores.

La conversión dependería de la lectura de la entrada con el backend CSV, escribir usando el backend XML. Esto es más fácil de hacer si tiene (o puede definir) un POJO para entradas por fila (CSV). Este no es un requisito estricto, ya que el contenido de CSV puede ser lea "untyped" también (una secuencia de matrices String), pero requiere un poco más de trabajo en la salida XML.

Para el lado XML, necesitaría un objeto raíz de envoltura para contener una matriz o List de objetos para serializar.

 4
Author: StaxMan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-29 20:01:12

Tuve el mismo problema y necesitaba una aplicación para convertir un archivo CSV a un archivo XML para uno de mis proyectos, pero no encontré nada gratuito y lo suficientemente bueno en la red, así que codifiqué mi propia aplicación Java Swing CsvToXml.

Está disponible en mi sitio web AQUÍ. Espero que te ayude.

Si no, puede codificar fácilmente el suyo propio como lo hice yo; El código fuente está dentro del archivo jar, así que modifíquelo según lo necesite si no cumple con sus requisitos.

 3
Author: Ibrabel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-18 11:14:48

Para la Parte CSV, puedes usar mi pequeña biblioteca de código abierto

 3
Author: Arne Burmeister,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-20 19:07:38