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

votos
95

¿Existe una aplicación o biblioteca existente en Java que me permita convertir un CSVarchivo de datos en un XMLarchivo?

Las XMLetiquetas se proporcionarán posiblemente a través de la primera fila que contenga encabezados de columna.

Publicado el 01/08/2008 a las 17:08
fuente por usuario
En otros idiomas...                            


16 respuestas

votos
3

Puede ser una solución demasiado básica o limitada, pero no podría hacer una String.split()en cada línea del archivo, recordar 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 el XML adecuado elementos de relleno cada iteración de un bucle?

Respondida el 01/08/2008 a las 17:31
fuente por usuario

votos
60

Tal vez esto podría ayudar: JSefa

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

Respondida el 01/08/2008 a las 19:51
fuente por usuario

votos
13

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

La conversión de un archivo CSV a XML no agrega 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 serializarlo a XML tiene sentido (bueno, tanto como usar XML puede tener sentido ...;)) pero supuestamente ya tienes un medio de serializando a XML.

Respondida el 01/08/2008 a las 20:21
fuente por usuario

votos
7

Por lo que yo sé, no hay una biblioteca preparada para hacer esto por ti, pero producir una herramienta capaz de traducir de CSV a XML solo requiere que escribas un analizador CSV crudo y conectes JDOM (o tu biblioteca XML Java de elección) con algún código de pegamento.

Respondida el 02/08/2008 a las 20:06
fuente por usuario

votos
7

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

  • Un marco de analizador CSV
  • Un marco de serialización XML

El analizador de CSV que recomendaría (a menos que quiera divertirse un poco al escribir su propio CSV Parser) es OpenCSV (A SourceForge Project para analizar datos de CSV)

El XML Serialization Framework debería ser algo que pueda escalar en caso de que desee transformar un archivo CSV grande (o enorme) en XML: mi recomendación es el Framework SunMS XML Streaming XML (Consulte aquí ) que permite el análisis y la serialización pull.

Respondida el 04/08/2008 a las 02:07
fuente por usuario

votos
24

Sé que solicitó Java, pero esto me parece una tarea adecuada para un lenguaje de scripting. Aquí hay una solución rápida (muy simple) escrita en 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])
            }
        }
    }
}

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 realiza un análisis muy simple (sin tener en cuenta comas entre comillas o escapadas) y no tiene en cuenta posibles datos ausentes.

Respondida el 09/08/2008 a las 12:06
fuente por usuario

votos
15

Esta solución no necesita ninguna biblioteca CSV o XML y, como sé, no maneja ningún carácter ilegal ni problemas de codificación, pero también podría estar interesado en ella, 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 posibilidad de utilizar una biblioteca adicional (posible en algunos proyectos burocráticos) ... Use un StringBuffer para entornos de ejecución más antiguos ...

Así que, 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 entrada test.csv (robada 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

El resultado 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>
Respondida el 22/08/2008 a las 00:17
fuente por usuario

votos
45

Como los otros anteriores, no conozco ninguna manera de hacer eso en un solo paso, pero si está listo para usar bibliotecas externas muy simples, sugeriría:

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

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

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

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 un ajuste muy fino 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>
Respondida el 10/09/2008 a las 08:06
fuente por usuario

votos
3

Para la parte CSV, puede usar mi pequeña biblioteca de código abierto

Respondida el 16/09/2008 a las 17:07
fuente por usuario