2008-08-01 42 views
92

¿Existe una aplicación o biblioteca en Java que me permita convertir un archivo de datos CSV en el archivo XML?¿Java lib o aplicación para convertir archivos CSV a XML?

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

+33

Parece que esta es la primera pregunta con la etiqueta de Java en SO. –

+6

@Paul ¡No solo eso, también es 123! – bjb568

+0

@ bjb568 ¿Qué quieres decir? – CodingNinja

Respuesta

59

Tal vez esto podría ayudar: JSefa

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

4

Esto puede ser una solución demasiado básica o limitada, pero no podría hacer un String.split() en cada línea del archivo, recordar el conjunto 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 rellenando cada iteración de un ciclo?

+1

No si su archivo CSV contiene alguna vez comas en datos, lo cual es bastante común. –

13

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

Convertir 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 otra parte, la lectura del archivo CSV, haciendo algo con los valores, y luego serializar a XML tiene sentido (bueno, tanto como el uso de XML puede tener sentido ...;)), pero que le supuestamente ya tiene un medio de serialización a XML.

7

Hasta donde yo 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 de CSV crudo y conecte JDOM (o su XML de la biblioteca Java de elección) con algún código de pegamento.

7

No hay nada que conozco que puede hacer esto sin que, al menos, escribir un poco de código ... Usted necesitará 2 biblioteca independiente:

  • Un analizador CSV Marco
  • una serialización XML marco

El analizador CSV recomendaría (a menos que desee tener un poco de diversión a escribir su propio analizador CSV) es OpenCSV (un proyecto de SourceForge para analizar datos CSV)

El XML Serialization Framework debería ser algo que pueda escalar en caso de que desee transformar un archivo CSV grande (o enorme) a XML: Mi recomendación es Sun Java Streaming XML Parser Framework (Ver here) que permite el análisis de pull Y serialización.

24

Sé que pidió 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.maravilloso

#!/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 código XML a la salida estándar:

<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 análisis muy simple (sin tener en cuenta citado o escapado comas) y no dar cuenta de posibles datos ausentes .

+0

Entonces podría llamar a una biblioteca CSV para hacer el análisis sintáctico y luego usar el generador de marcas. Tal vez podrías editar tu respuesta para mostrar esto. –

+0

Ejercicio dejado al lector? –

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 puede que también le interese, siempre que su entrada CSV no supere lo mencionado anteriormente. reglas.

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

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

El test.csv entrada (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> 
44

Como los demás por encima, no sé de ninguna manera de un solo paso para hacer eso, pero si usted está listo para usar bibliotecas externas muy simples, sugeriría:

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

Xstream para analizar/XML serializar (muy, muy fácil de usar, y la creación de XML legible completamente humano)

Usando los mismos datos de ejemplo 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(); 
     } 
    } 
} 

Producir el siguiente resultado: (Xstream permite muy puesta a punto 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> 
3

Para el CSV Parte, puede usar my little open source library

+0

¿Tiene otro enlace para su biblioteca? El enlace está muerto. Esta es, por cierto, la razón exacta por la cual se fomentan las respuestas al enlace único. – Magnilex

17

Tengo un marco de código abierto para trabajar con CSV y archivos planos en general. Tal vez vale la pena mirar: JFileHelpers.

Con kit de herramientas que se puede escribir código usando granos, 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 analizar sintácticamente los 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á una colección de objetos analizada.

Espero que ayude!

+0

+1 para el uso de anotaciones. Desafortunadamente, a partir de hoy, parece que el proyecto no tiene ninguna versión nueva desde 2009-08-11 ... – Stephan

+0

Sí, no tuve tiempo para continuar con el desarrollo desde entonces, pero es muy estable. – kolrie

8

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

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

15

Puede hacerlo de forma excepcionalmente fácil con Groovy, y el código es muy legible.

Básicamente, la variable de texto se escribirá en contacts.xml para cada línea en el contactData.csv, y la matriz de campos 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>""" 
} 
+5

CSV es simple, pero generalmente nunca es tan simple que una división en la coma es suficiente. –

11

Usted podría utilizar XSLT. Google y encontrará algunos ejemplos, p. CSV to XML Si usa XSLT, puede convertir el XML al formato que desee.

14

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

JFileHelpers también parece interesante.

3

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 gratis y lo suficientemente bueno en la red, así que codifiqué mi propio Java Swing CSVtoXML solicitud.

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

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

3

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

La conversión se basaría en la lectura de la entrada con el backend CSV, escribir con 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 también puede leerse como "sin tipo" (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 contenedor para contener una matriz o List de objetos para serializar.