Lib Java atau aplikasi untuk mengonversi CSV ke file XML? [Tutup]

114

Apakah ada aplikasi atau pustaka yang ada di Java yang memungkinkan saya mengonversi CSVfile data ke XMLfile?

The XMLtag akan diberikan melalui mungkin baris pertama yang berisi judul kolom.

A Salim
sumber
47
Tampaknya ini adalah pertanyaan pertama dengan tag Java di SO.
Paul Vargas
8
@Paul Tidak hanya itu, ini juga 123!
bjb568
1
@Tommy stackoverflow.com/q/123
bjb568
1
@ bjm_hhh. haha
4
Pantas saja posting pertama untuk java di SO ditutup karena di luar topik: D
Pak. Landak

Jawaban:

66

Mungkin ini bisa membantu: JSefa

Anda dapat membaca file CSV dengan alat ini dan membuatnya berseri menjadi XML.

svrist
sumber
47

Seperti yang lain di atas, saya tidak tahu cara satu langkah untuk melakukan itu, tetapi jika Anda siap menggunakan pustaka eksternal yang sangat sederhana, saya sarankan:

OpenCsv untuk mengurai CSV (kecil, sederhana, andal, dan mudah digunakan)

Xstream untuk mengurai / membuat serial XML (sangat sangat mudah digunakan, dan membuat xml yang dapat dibaca sepenuhnya oleh manusia)

Menggunakan contoh data yang sama seperti di atas, kode akan terlihat seperti ini:

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

Memproduksi hasil sebagai berikut: (Xstream memungkinkan penyetelan hasil yang sangat baik ...)

<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>
Laurent K
sumber
27

Saya tahu Anda meminta Java, tetapi menurut saya tugas ini sangat cocok untuk bahasa skrip. Berikut adalah solusi cepat (sangat sederhana) yang ditulis dalam 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])
            }
        }
    }
}

Menulis XML berikut ke 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>

Namun, kode melakukan parsing yang sangat sederhana (tidak memperhitungkan tanda kutip atau tanda koma) dan tidak memperhitungkan kemungkinan data yang tidak ada.

Anthony Cramp
sumber
Jadi, Anda dapat memanggil pustaka CSV untuk melakukan parsing dan kemudian menggunakan pembuat markup. Mungkin Anda bisa mengedit jawaban Anda untuk menunjukkan ini.
Peter Kelley
18

Saya memiliki kerangka kerja sumber terbuka untuk bekerja dengan CSV dan file datar secara umum. Mungkin itu layak untuk dilihat: JFileHelpers .

Dengan toolkit itu Anda dapat menulis kode menggunakan kacang, seperti:

@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;  
}

lalu parsing file teks Anda menggunakan:

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

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

Dan Anda akan memiliki koleksi objek yang diurai.

Semoga membantu!

kolrie
sumber
+1 untuk penggunaan anotasi. Sayangnya, pada hari ini, tampaknya proyek tersebut tidak memiliki versi baru sejak 2009-08-11 ...
Stephan
Ya, saya tidak punya waktu untuk melanjutkan pengembangan sejak itu tetapi sangat stabil.
kolrie
17

Solusi ini tidak memerlukan pustaka CSV atau XML dan, saya tahu, ini tidak menangani karakter ilegal dan masalah pengkodean, tetapi Anda mungkin tertarik juga, asalkan masukan CSV Anda tidak melanggar aturan yang disebutkan di atas.

Perhatian: Anda tidak boleh menggunakan kode ini kecuali Anda tahu apa yang Anda lakukan atau tidak memiliki kesempatan untuk menggunakan perpustakaan lebih lanjut (mungkin dalam beberapa proyek birokrasi) ... Gunakan StringBuffer untuk Lingkungan Waktu Proses yang lebih lama ...

Jadi ini dia:

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

The input test.csv (dicuri dari jawaban lain di halaman ini):

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

Output yang dihasilkan:

<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>
Martin Klinke
sumber
15

Perbedaan besar adalah bahwa JSefa membawa masuk adalah bahwa ia dapat membuat serial objek java Anda ke file CSV / XML / etc dan dapat deserialisasi kembali ke objek java. Dan itu didorong oleh anotasi yang memberi Anda banyak kendali atas hasilnya.

JFileHelpers juga terlihat menarik.

James Selvakumar
sumber
14

Saya tidak mengerti mengapa Anda ingin melakukan ini. Kedengarannya hampir seperti pengkodean kultus kargo.

Mengonversi file CSV ke XML tidak menambah nilai apa pun. Program Anda sudah membaca file CSV, jadi berargumen bahwa Anda memerlukan XML tidak akan berfungsi.

Di sisi lain, membaca file CSV, melakukan sesuatu dengan nilai, dan kemudian membuat serial ke XML memang masuk akal (yah, sebanyak menggunakan XML bisa masuk akal ...;)) tetapi Anda seharusnya sudah memiliki cara untuk serialisasi ke XML.

Ryan Fox
sumber
14

Anda dapat melakukan ini dengan sangat mudah menggunakan Groovy, dan kodenya sangat mudah dibaca.

Pada dasarnya, variabel teks akan ditulis contacts.xmluntuk setiap baris di contactData.csv, dan array bidang berisi setiap kolom.

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>"""
}
abarax
sumber
7
CSV sederhana, tetapi umumnya tidak pernah cukup sederhana sehingga pemisahan di koma sudah cukup.
Alan Krueger
12

Anda bisa menggunakan XSLT . Google dan Anda akan menemukan beberapa contoh misalnya CSV ke XML Jika Anda menggunakan XSLT Anda kemudian dapat mengubah XML ke format apa pun yang Anda inginkan.

Simmo
sumber
8

Ada juga perpustakaan ServingXML yang bagus oleh Daniel Parker, yang mampu mengonversi hampir semua format teks biasa ke XML dan sebaliknya .

Contoh kasus Anda dapat ditemukan di sini : Menggunakan heading of field dalam file CSV sebagai nama elemen XML.

Lukáš Rampa
sumber
7

Tidak ada yang saya ketahui yang dapat melakukan ini tanpa Anda setidaknya menulis sedikit kode ... Anda akan memerlukan 2 perpustakaan terpisah:

  • Kerangka Parser CSV
  • Kerangka Serialisasi XML

Pengurai CSV yang akan saya rekomendasikan (kecuali jika Anda ingin sedikit bersenang-senang untuk menulis Parser CSV Anda sendiri) adalah OpenCSV (Proyek SourceForge untuk mengurai Data CSV)

XML Serialization Framework haruslah sesuatu yang dapat diskalakan jika Anda ingin mengubah file CSV yang besar (atau sangat besar) ke XML: Rekomendasi saya adalah Sun Java Streaming XML Parser Framework (Lihat di sini ) yang memungkinkan penguraian dan serialisasi tarik.

Claude Houle
sumber
7

Sejauh yang saya tahu, tidak ada pustaka siap pakai untuk melakukan ini untuk Anda, tetapi menghasilkan alat yang mampu menerjemahkan dari CSV ke XML seharusnya hanya mengharuskan Anda untuk menulis parser CSV mentah dan menghubungkan JDOM (atau pustaka XML Java Anda pilihan) dengan beberapa kode lem.

Matt
sumber
4

Keluarga prosesor Jackson memiliki backend untuk berbagai format data, tidak hanya JSON. Ini termasuk backend XML ( https://github.com/FasterXML/jackson-dataformat-xml ) dan CSV ( https://github.com/FasterXML/jackson-dataformat-csv/ ).

Konversi akan bergantung pada membaca input dengan backend CSV, menulis menggunakan backend XML. Ini paling mudah dilakukan jika Anda memiliki (atau dapat menentukan) POJO untuk entri per baris (CSV). Ini bukan persyaratan yang ketat, karena konten dari CSV juga dapat dibaca "tanpa tipe" (urutan Stringarray), tetapi memerlukan sedikit lebih banyak pekerjaan pada keluaran XML.

Untuk sisi XML, Anda memerlukan objek root pembungkus untuk memuat larik atau Listobjek untuk diserialkan.

StaxMan
sumber
3

Saya memiliki masalah yang sama dan memerlukan aplikasi untuk mengonversi file CSV menjadi file XML untuk salah satu proyek saya, tetapi tidak menemukan sesuatu yang gratis dan cukup bagus di internet, jadi saya membuat kode aplikasi CSVtoXML Java Swing saya sendiri.

Ini tersedia dari situs web saya DI SINI . Semoga bisa membantu Anda.

Jika tidak, Anda dapat dengan mudah membuat kode sendiri seperti yang saya lakukan; Kode sumber ada di dalam file jar jadi ubah sesuai kebutuhan jika tidak memenuhi kebutuhan Anda.

Ibrabel
sumber
3

Ini mungkin solusi yang terlalu mendasar atau terbatas, tetapi tidak bisakah Anda melakukan String.split()pada setiap baris file, mengingat larik hasil dari baris pertama untuk menghasilkan XML, dan hanya mengeluarkan data larik setiap baris dengan XML yang tepat elemen padding setiap iterasi loop?

saint_groceon
sumber
2
Tidak jika file CSV Anda pernah berisi tanda kutip dalam data, yang cukup umum.
Alan Krueger