Pregunta

¿Existe una aplicación o biblioteca existente en Java lo que me permitirá convertir un CSV archivo de datos a XML ¿archivo?

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

¿Fue útil?

Solución

Quizás esto pueda ayudar: JSefa

Puede leer archivos CSV con esta herramienta y serializarlos a XML.

Otros consejos

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

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

Xstream analizar/serializar XML (muy, muy fácil de usar y crea xml totalmente legible por humanos)

Usando los mismos datos de muestra que arriba, 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>

Sé que pediste Java, pero me parece una tarea que se adapta bien a un lenguaje de secuencias de comandos.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 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 realiza un análisis muy simple (sin tener en cuenta las comas entre comillas o escapes) y no tiene en cuenta posibles datos ausentes.

Tengo un marco de código abierto para trabajar con CSV y archivos planos en general.Quizás valga 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 ayude!

Esta solución no necesita bibliotecas CSV o XML y, lo sé, no maneja caracteres ilegales ni problemas de codificación, pero es posible que a usted también le interese, siempre que su entrada CSV no infrinja las reglas mencionadas anteriormente.

Atención: No deberías usar este código a menos que sepas lo que haces o no tengas la oportunidad de usar una biblioteca adicional (posible en algunos proyectos burocráticos)...Utilice 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

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>

La gran diferencia es que JSefa Lo que aporta es que puede serializar sus objetos Java en archivos CSV/XML/etc y puede deserializarlos nuevamente en objetos Java.Y está impulsado por anotaciones que le brindan mucho control sobre la salida.

JFileHelpers también parece interesante.

No entiendo por qué querrías hacer esto.Suena casi a codificación de culto a la 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 otro lado, leer el archivo CSV, hacer algo con los valores, y luego serializar a XML tiene sentido (bueno, por mucho que usar XML pueda tener sentido...;)) pero supuestamente ya tendrías un medio para serializar a XML.

Puedes hacer esto excepcionalmente fácilmente usando 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>"""
}

Podrías usar XSLT.Busque en Google y encontrará algunos ejemplos, p. CSV a XMLSi utiliza XSLT Luego puede convertir el XML al formato que desee.

También hay una buena biblioteca. Sirviendo XML 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 nombre del elemento XML.

No conozco nada 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 marco de serialización XML

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

El marco de serialización XML debería ser algo que pueda escalarse en caso de que desee transformar un archivo CSV grande (o enorme) a XML:Mi recomendación es Sun Java Streaming XML Parser Framework (consulte aquí) que permite el análisis de extracción Y la serialización.

Hasta donde yo sé, no existe una biblioteca lista 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 básico y conecte JDOM (o su biblioteca XML Java de elección) con algún código de pegamento.

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/) servidores.

La conversión dependería de leer la entrada con el backend CSV y 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 también se puede leer "sin escribir" (una secuencia de String matrices), pero requiere un poco más de trabajo en la salida XML.

Para el lado XML, necesitaría un objeto raíz contenedor que contenga una matriz o List de objetos a serializar.

Esta puede ser una solución demasiado básica o limitada, pero ¿no podrías 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 los elementos XML adecuados rellenando cada iteración de un bucle?

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, puedes codificar fácilmente el tuyo como lo hice yo;El código fuente está dentro del archivo jar, así que modifíquelo según sea necesario si no cumple con sus requisitos.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top