Domanda

Esiste un'applicazione o una libreria esistente in Giava che mi permetterà di convertire a CSV file di dati in XML file?

IL XML i tag verrebbero forniti possibilmente attraverso la prima riga contenente le intestazioni di colonna.

È stato utile?

Soluzione

Forse questo potrebbe aiutare: JSefa

Puoi leggere il file CSV con questo strumento e serializzarlo in XML.

Altri suggerimenti

Come gli altri sopra, non conosco alcun modo in un solo passaggio per farlo, ma se sei pronto per utilizzare librerie esterne molto semplici, suggerirei:

OpenCsv per l'analisi CSV (piccolo, semplice, affidabile e facile da usare)

Xstream per analizzare/serializzare XML (molto molto facile da usare e creare XML completamente leggibile dall'uomo)

Utilizzando gli stessi dati di esempio di cui sopra, il codice sarebbe simile a:

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

Producendo il seguente risultato:(Xstream consente una regolazione molto precisa del risultato...)

<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>

So che hai chiesto Java, ma questo mi sembra un compito adatto a un linguaggio di scripting.Ecco una soluzione rapida (molto semplice) scritta in Groovy.

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

Scrive il seguente XML su 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>

Tuttavia, il codice esegue un'analisi molto semplice (non tenendo conto delle virgole tra virgolette o caratteri di escape) e non tiene conto di eventuali dati assenti.

Ho un framework open source per lavorare con CSV e file flat in generale.Forse vale la pena guardare: JFileHelpers.

Con quel toolkit puoi scrivere codice usando bean, come:

@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 poi analizza i tuoi file di testo usando:

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

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

E avrai una raccolta di oggetti analizzati.

Spero che aiuti!

Questa soluzione non necessita di librerie CSV o XML e, lo so, non gestisce caratteri illegali e problemi di codifica, ma potrebbe interessarti anche tu, a condizione che il tuo input CSV non infranga le regole sopra menzionate.

Attenzione: Non dovresti usare questo codice a meno che tu non sappia cosa fai o non hai la possibilità di utilizzare un'ulteriore libreria (possibile in alcuni progetti burocratici)...Utilizza uno StringBuffer per ambienti runtime precedenti...

Quindi eccoci qua:

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

L'input test.csv (rubato da un'altra risposta in questa pagina):

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

L'output risultante:

<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 grande differenza è questa JSefa porta è che può serializzare i tuoi oggetti Java in file CSV/XML/etc e può deserializzare nuovamente in oggetti Java.Ed è guidato da annotazioni che ti danno molto controllo sull'output.

Anche JFileHelpers sembra interessante.

Non capisco perché vorresti farlo.Sembra quasi una codifica del culto del carico.

La conversione di un file CSV in XML non aggiunge alcun valore.Il tuo programma sta già leggendo il file CSV, quindi sostenere che hai bisogno di XML non funziona.

D'altra parte, leggendo il file CSV, facendo qualcosa con i valori, e quindi la serializzazione in XML ha senso (beh, per quanto l'uso di XML possa avere senso...;)) ma presumibilmente avresti già un mezzo per serializzare in XML.

Puoi farlo eccezionalmente facilmente usando Groovy e il codice è molto leggibile.

Fondamentalmente, verrà scritta la variabile text contacts.xml per ogni riga del file contactData.csv, e la matrice dei campi contiene ciascuna colonna.

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>"""
}

Potresti usare XSLT.Cercalo su Google e troverai alcuni esempi, ad es. CSV in XMLSe usi XSLT puoi quindi convertire l'XML nel formato che desideri.

C'è anche una buona biblioteca ServingXML di Daniel Parker, che è in grado di convertire quasi tutti i formati di testo semplice in XML e viceversa.

L'esempio per il tuo caso può essere trovato Qui:Utilizza l'intestazione del campo nel file CSV come nome dell'elemento XML.

Non c'è niente che io sappia che possa farlo senza che tu almeno scriva un po' di codice...Avrai bisogno di 2 librerie separate:

  • Un framework per parser CSV
  • Un framework di serializzazione XML

Il parser CSV che consiglierei (a meno che tu non voglia divertirti un po' a scrivere il tuo parser CSV) è OpenCSV (A SourceForge Project for parsing CSV Data)

Il framework di serializzazione XML dovrebbe essere qualcosa che possa essere scalato nel caso in cui desideri trasformare un file CSV di grandi dimensioni (o enorme) in XML:Il mio consiglio è Sun Java Streaming XML Parser Framework (vedi Qui) che consente l'analisi pull E la serializzazione.

Per quanto ne so, non esiste una libreria già pronta per fare questo per te, ma produrre uno strumento in grado di tradurre da CSV a XML dovrebbe solo richiedere che tu scriva un parser CSV grezzo e colleghi JDOM (o la tua libreria Java XML di scelta) con qualche codice adesivo.

La famiglia di processori Jackson dispone di backend per più formati di dati, non solo JSON.Ciò include sia XML (https://github.com/FasterXML/jackson-dataformat-xml) e CSV (https://github.com/FasterXML/jackson-dataformat-csv/) backend.

La conversione si baserebbe sulla lettura dell'input con il backend CSV, sulla scrittura utilizzando il backend XML.Questo è più semplice da fare se hai (o puoi definire) un POJO per voci per riga (CSV).Questo non è un requisito rigoroso, poiché il contenuto di CSV può essere letto anche "non digitato" (una sequenza di file String array), ma richiede un po' più di lavoro sull'output XML.

Per il lato XML, sarebbe necessario un oggetto root wrapper per contenere array o List di oggetti da serializzare.

Questa potrebbe essere una soluzione troppo semplice o limitata, ma non potresti fare a String.split() su ogni riga del file, ricordando l'array dei risultati della prima riga per generare l'XML e semplicemente sputando i dati dell'array di ogni riga con gli elementi XML corretti che riempiono ogni iterazione di un ciclo?

Ho avuto lo stesso problema e avevo bisogno di un'applicazione per convertire un file CSV in un file XML per uno dei miei progetti, ma non ho trovato nulla di gratuito e abbastanza buono in rete, quindi ho codificato la mia applicazione Java Swing CSVtoXML.

È disponibile dal mio sito web QUI.Spero che ti aiuterà.

In caso contrario, puoi facilmente codificarne uno tuo come ho fatto io;Il codice sorgente è all'interno del file jar, quindi modificalo secondo necessità se non soddisfa i tuoi requisiti.

Per la parte CSV, puoi utilizzare la mia piccola libreria open source

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top