CSV'yi XML dosyasına dönüştürmek için Java kitaplığı veya uygulaması? [kapalı]


114

Java'da bir CSVveri dosyasını dosyaya dönüştürmeme izin verecek mevcut bir uygulama veya kitaplık var mı XML?

XMLEtiketler sütun başlıkları içeren muhtemelen ilk satırı boyunca sağlanmış olacaktır.


47
Görünüşe göre bu, SO'daki Java etiketiyle ilgili ilk soru.
Paul Vargas

8
@Paul Sadece bu değil, aynı zamanda 123!
bjb568


1
@hayalhanemersin haha

4
SO'daki java için ilk gönderinin konu dışı olarak kapatılmasına şaşmamalı: D
Efendim. Kirpi

Yanıtlar:


66

Belki bu yardımcı olabilir: JSefa

CSV dosyasını bu araçla okuyabilir ve XML olarak serileştirebilirsiniz.


47

Yukarıdaki diğerleri gibi, bunu yapmanın tek adımlı bir yolunu bilmiyorum, ancak çok basit harici kitaplıkları kullanmaya hazırsanız, şunları öneririm:

CSV'yi ayrıştırmak için OpenCsv (küçük, basit, güvenilir ve kullanımı kolay)

XML'i ayrıştırmak / serileştirmek için Xstream (kullanımı çok kolay ve tamamen insan tarafından okunabilir xml oluşturma)

Yukarıdakiyle aynı örnek verileri kullanarak, kod şöyle görünür:

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

Aşağıdaki sonucun oluşturulması: (Xstream, sonucun çok ince ayarlanmasına izin verir ...)

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

27

Java istediğini biliyorum, ama bu beni bir betik diline çok uygun bir görev olarak etkiliyor. İşte Groovy'de yazılmış hızlı (çok basit) bir çözüm.

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

Aşağıdaki XML'yi standart çıktıya yazar:

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

Bununla birlikte, kod çok basit bir çözümleme yapar (alıntılanan veya kaçan virgülleri hesaba katmadan) ve olası eksik verileri hesaba katmaz.


Böylece, ayrıştırmayı yapmak için bir CSV kitaplığı çağırabilir ve ardından işaretleme oluşturucuyu kullanabilirsiniz. Belki cevabınızı bunu gösterecek şekilde düzenleyebilirsiniz.
Peter Kelley

18

Genel olarak CSV ve düz dosyalarla çalışmak için açık kaynaklı bir çerçevem ​​var. Belki bakmaya değer: JFileHelpers .

Bu araç takımı ile fasulye kullanarak kod yazabilirsiniz, örneğin:

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

ve ardından metin dosyalarınızı şu şekilde ayrıştırın:

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

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

Ve ayrıştırılmış nesnelerden oluşan bir koleksiyonunuz olacak.

Umarım yardımcı olur!


Ek açıklamaların kullanımı için +1. Ne yazık ki, bugün itibariyle, projenin 2009-08-11'den beri yeni bir sürümü yok gibi görünüyor ...
Stephan

Evet, o zamandan beri geliştirmeye devam edecek vaktim olmadı ama çok kararlı.
kolrie

17

Bu çözüm herhangi bir CSV veya XML kitaplığına ihtiyaç duymaz ve biliyorum, yasadışı karakterleri ve kodlama sorunlarını ele almaz, ancak CSV girişinizin yukarıda belirtilen kuralları ihlal etmemesi koşuluyla, bununla da ilgilenebilirsiniz.

Dikkat: Ne yaptığınızı bilmiyorsanız veya başka bir kitaplık kullanma şansınız olmadıkça bu kodu kullanmamalısınız (bazı bürokratik projelerde mümkündür) ... Eski Çalışma Zamanı Ortamları için bir StringBuffer kullanın ...

İşte başlıyoruz:

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

Giriş test.csv (bu sayfadaki başka bir cevaptan çalındı):

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

Ortaya çıkan çıktı:

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

15

JSefa'nın getirdiği en büyük fark, java nesnelerinizi CSV / XML / etc dosyalarına serileştirebilmesi ve java nesnelerine yeniden serileştirebilmesidir. Ve çıktı üzerinde size çok fazla kontrol sağlayan ek açıklamalarla yönlendirilir.

JFileHelpers da ilginç görünüyor.


14

Bunu neden yapmak isteyeceğini anlamıyorum. Neredeyse kargo kült kodlamasına benziyor.

Bir CSV dosyasını XML'e dönüştürmek herhangi bir değer katmaz. Programınız zaten CSV dosyasını okuyor, bu nedenle XML'e ihtiyacınız olduğunu savunmak işe yaramıyor.

Öte yandan, CSV dosyasını okumak, değerlerle bir şeyler yapmak ve ardından XML'e serileştirmek mantıklıdır (XML kullanmanın mantıklı olabileceği kadar ...;) ama sözüm ona zaten XML'e serileştirme.


14

Bunu Groovy kullanarak son derece kolay bir şekilde yapabilirsiniz ve kod çok okunabilir.

Temel olarak, metin değişkeni contacts.xmliçindeki her satır için yazılır contactData.csvve alanlar dizisi her sütunu içerir.

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

7
CSV basittir, ancak genellikle virgülle ayırmanın yeterli olacağı kadar basit değildir.
Alan Krueger

12

XSLT kullanabilirsiniz . Google it ve birkaç örnek bulacaksınız, örneğin CSV'den XML'e XSLT kullanıyorsanız , XML'i istediğiniz biçime dönüştürebilirsiniz.


8

Hemen hemen her düz metin biçimini XML'e ve geri dönüştürebilen Daniel Parker'ın sunduğu ServingXML adlı iyi bir kitaplık da vardır .

Durumunuza ilişkin örnek burada bulunabilir : XML öğe adı olarak CSV dosyasındaki alan başlığını kullanır.


7

En azından biraz kod yazmadan bunu yapabileceğini bildiğim hiçbir şey yok ... 2 ayrı kitaplığa ihtiyacınız olacak:

  • CSV Ayrıştırıcı Çerçevesi
  • XML Serileştirme Çerçevesi

Tavsiye edeceğim CSV ayrıştırıcısı (kendi CSV Ayrıştırıcınızı yazmak için biraz eğlenmek istemiyorsanız) OpenCSV'dir (CSV Verilerini ayrıştırmak için bir SourceForge Projesi)

XML Serileştirme Çerçevesi, büyük (veya çok büyük) CSV dosyasını XML'e dönüştürmek istemeniz durumunda ölçeklenebilecek bir şey olmalıdır: Benim önerim , çek-ayrıştırmaya VE serileştirmeye izin veren Sun Java Akışı XML Ayrıştırıcı Çerçevesidir ( buraya bakın ).


7

Bildiğim kadarıyla, bunu sizin için yapacak hazır bir kitaplık yok, ancak CSV'den XML'e çeviri yapabilen bir araç üretmek yalnızca ham bir CSV ayrıştırıcısı yazmanızı ve JDOM'u (veya XML Java kitaplığınızı bazı tutkal kodu ile.


4

Jackson işlemci ailesi, yalnızca JSON için değil, birden çok veri formatı için arka uçlara sahiptir. Buna hem XML ( https://github.com/FasterXML/jackson-dataformat-xml ) hem de CSV ( https://github.com/FasterXML/jackson-dataformat-csv/) dahildir. ) arka uçları dahildir.

Dönüşüm, girişin CSV arka uç ile okunmasına dayanır, XML arka uç kullanarak yazılır. Satır başına (CSV) girişler için bir POJO'ya sahipseniz (veya tanımlayabiliyorsanız) bunu yapmak en kolay yoldur. CSV içeriği "türlenmemiş" olarak da okunabileceğinden bu katı bir gereklilik değildir (bir diziString dizi) , ancak XML çıktısı üzerinde biraz daha fazla çalışma gerektirir.

XML tarafı için, diziyi veya Listserileştirilecek nesneleri içeren bir sarmalayıcı kök nesnesine ihtiyacınız olacaktır .


3

Aynı sorunu yaşadım ve projelerimden biri için bir CSV dosyasını XML dosyasına dönüştürmek için bir uygulamaya ihtiyacım vardı, ancak internette özgür ve yeterince iyi bir şey bulamadım, bu yüzden kendi Java Swing CSVtoXML uygulamamı kodladım.

BURAYA web sitemden edinilebilir . Umarım size yardımcı olur.

Değilse, benim yaptığım gibi kendi kodunuzu kolayca kodlayabilirsiniz; Kaynak kodu jar dosyasının içindedir, bu nedenle gereksinimlerinizi karşılamıyorsa ihtiyacınız olduğu gibi değiştirin.



3

Bu, bir çözüm için çok basit veya sınırlı olabilir, ancak String.split()dosyanın her satırında, XML'yi oluşturmak için ilk satırın sonuç dizisini hatırlayarak ve her satırın dizi verilerini uygun XML ile tüküremezsiniz. bir döngünün her yinelemesini dolduran öğeler?


2
CSV dosyanızın verilerinde alıntılanmış virgül içermiyorsa, bu oldukça yaygındır.
Alan Krueger
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.