Java lib หรือแอพเพื่อแปลงไฟล์ CSV เป็น XML? [ปิด]


114

มีแอปพลิเคชันหรือไลบรารีที่มีอยู่ในJavaซึ่งจะช่วยให้ฉันสามารถแปลงCSVไฟล์ข้อมูลเป็นXMLไฟล์ได้หรือไม่?

XMLแท็กจะให้ผ่านอาจจะเป็นแถวแรกที่มีส่วนหัวของคอลัมน์


47
ดูเหมือนว่านี่เป็นคำถามแรกที่มีแท็ก Java ใน SO
Paul Vargas

8
@ พอลไม่เพียงแค่นั้นยังเป็น 123!
bjb568


1
@ bjb568 อ๋อ. haha

4
ไม่น่าแปลกใจที่โพสต์แรกสำหรับ java ใน SO ถูกปิดเป็นนอกหัวข้อ: D
Sir Hedgehog

คำตอบ:


66

บางทีนี่อาจช่วยได้: JSefa

คุณสามารถอ่านไฟล์ CSV ด้วยเครื่องมือนี้และทำให้เป็นไฟล์ XML


47

ดังที่กล่าวมาข้างต้นฉันไม่รู้วิธีขั้นตอนเดียวในการทำเช่นนั้น แต่ถ้าคุณพร้อมที่จะใช้ไลบรารีภายนอกที่เรียบง่ายฉันขอแนะนำ:

OpenCsvสำหรับการแยกวิเคราะห์ CSV (ขนาดเล็กเรียบง่ายเชื่อถือได้และใช้งานง่าย)

Xstreamเพื่อแยกวิเคราะห์ / ทำให้เป็นอนุกรม XML (ใช้งานง่ายมากและสร้าง xml ที่มนุษย์อ่านได้อย่างสมบูรณ์)

การใช้ข้อมูลตัวอย่างเดียวกันกับด้านบนโค้ดจะมีลักษณะดังนี้:

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

สร้างผลลัพธ์ต่อไปนี้: (Xstream อนุญาตให้ปรับแต่งผลลัพธ์ได้อย่างละเอียดมาก ... )

<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 แต่สิ่งนี้ทำให้ฉันรู้สึกว่าเป็นงานที่เหมาะกับภาษาสคริปต์ นี่คือวิธีแก้ปัญหาที่รวดเร็ว (ง่ายมาก) ที่เขียนด้วย 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])
            }
        }
    }
}

เขียน XML ต่อไปนี้เป็น 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>

อย่างไรก็ตามรหัสจะแยกวิเคราะห์ง่ายมาก (ไม่คำนึงถึงเครื่องหมายอัญประกาศหรือเครื่องหมายจุลภาคที่ใช้ Escape) และไม่ได้พิจารณาถึงข้อมูลที่อาจขาดหายไป


คุณสามารถเรียกไลบรารี CSV เพื่อทำการแยกวิเคราะห์จากนั้นใช้ตัวสร้างมาร์กอัป บางทีคุณอาจแก้ไขคำตอบเพื่อแสดงสิ่งนี้
Peter Kelley

18

ฉันมีเฟรมเวิร์กโอเพนซอร์ซสำหรับการทำงานกับ CSV และไฟล์แบบแบนโดยทั่วไป อาจจะคุ้มค่า: JFileHelpers JFileHelpers

ด้วยชุดเครื่องมือดังกล่าวคุณสามารถเขียนโค้ดโดยใช้ถั่วเช่น:

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

จากนั้นแยกวิเคราะห์ไฟล์ข้อความของคุณโดยใช้:

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

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

และคุณจะมีชุดของวัตถุที่แยกวิเคราะห์

หวังว่าจะช่วยได้!


+1 สำหรับการใช้คำอธิบายประกอบ น่าเสียดายที่ ณ วันนี้ดูเหมือนว่าโครงการจะไม่มีเวอร์ชันใหม่ตั้งแต่ปี 2009-08-11 ...
Stephan

ใช่ฉันไม่มีเวลาพัฒนาต่อตั้งแต่นั้นมา แต่มันเสถียรมาก
kolrie

17

โซลูชันนี้ไม่จำเป็นต้องใช้ไลบรารี CSV หรือ XML และฉันรู้ว่ามันไม่ได้จัดการกับอักขระที่ผิดกฎหมายและปัญหาการเข้ารหัส แต่คุณอาจสนใจมันเช่นกันหากอินพุต CSV ของคุณไม่ผิดกฎที่กล่าวถึงข้างต้น

เรียนควรคุณไม่ควรใช้รหัสนี้เว้นแต่คุณจะรู้ว่าคุณทำอะไรหรือไม่มีโอกาสใช้ไลบรารีเพิ่มเติม (เป็นไปได้ในบางโครงการของระบบราชการ) ... ใช้ StringBuffer สำหรับสภาพแวดล้อมรันไทม์รุ่นเก่า ...

ไปเลย:

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

อินพุต 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

ผลลัพธ์ที่ได้:

<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นำเข้ามาคือสามารถทำให้วัตถุ java ของคุณเป็นอนุกรมเป็นไฟล์ CSV / XML / etc และสามารถแยกขนาดกลับเป็นวัตถุ java ได้ และมันขับเคลื่อนด้วยคำอธิบายประกอบซึ่งช่วยให้คุณควบคุมผลลัพธ์ได้มาก

JFileHelpers ก็ดูน่าสนใจเช่นกัน


14

ฉันไม่เข้าใจว่าทำไมคุณถึงอยากทำแบบนี้ ดูเหมือนการเข้ารหัสลัทธิการขนส่งสินค้า

การแปลงไฟล์ CSV เป็น XML ไม่ได้เพิ่มมูลค่าใด ๆ โปรแกรมของคุณกำลังอ่านไฟล์ CSV อยู่แล้วดังนั้นการเถียงว่าคุณต้องการ XML จึงใช้ไม่ได้

ในทางกลับกันการอ่านไฟล์ CSV ทำอะไรบางอย่างกับค่าจากนั้นการทำให้เป็นอนุกรมเป็น XML นั้นสมเหตุสมผล (เช่นเดียวกับการใช้ XML ก็สมเหตุสมผล ... ;)) แต่คุณควรมีวิธีการอยู่แล้ว การทำให้เป็นอนุกรมกับ XML


14

คุณสามารถทำได้อย่างง่ายดายโดยใช้ Groovy และรหัสนี้อ่านได้ง่ายมาก

โดยทั่วไปตัวแปรข้อความจะถูกเขียนลงcontacts.xmlในแต่ละบรรทัดในcontactData.csvอาร์เรย์และฟิลด์อาร์เรย์ประกอบด้วยแต่ละคอลัมน์

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 นั้นง่าย แต่โดยทั่วไปแล้วจะไม่ง่ายพอที่จะทำให้การแบ่งในเครื่องหมายจุลภาคเพียงพอ
Alan Krueger

12

คุณสามารถใช้XSLT Google และคุณจะพบตัวอย่างบางส่วนเช่นCSV เป็น XML หากคุณใช้XSLTคุณสามารถแปลง XML เป็นรูปแบบใดก็ได้ที่คุณต้องการ


8

นอกจากนี้ยังมีห้องสมุดที่ดีServingXMLโดย Daniel Parker ซึ่งสามารถแปลงรูปแบบข้อความธรรมดาเกือบทุกรูปแบบเป็น XML และย้อนกลับได้

ตัวอย่างสำหรับกรณีของคุณสามารถพบได้ที่นี่ : ใช้ส่วนหัวของฟิลด์ในไฟล์ CSV เป็นชื่อองค์ประกอบ XML


7

ไม่มีอะไรที่ฉันรู้ว่าสามารถทำได้โดยที่คุณไม่ต้องเขียนโค้ดสักหน่อย ... คุณจะต้องมีห้องสมุด 2 แห่งแยกกัน:

  • CSV Parser Framework
  • XML Serialization Framework

โปรแกรมแยกวิเคราะห์ CSV ที่ฉันอยากจะแนะนำ (เว้นแต่คุณต้องการสนุกกับการเขียนตัวแยกวิเคราะห์ CSV ของคุณเอง) คือ OpenCSV (โครงการ SourceForge สำหรับการแยกวิเคราะห์ข้อมูล CSV)

XML Serialization Framework ควรเป็นสิ่งที่สามารถปรับขนาดได้ในกรณีที่คุณต้องการแปลงไฟล์ CSV ขนาดใหญ่ (หรือใหญ่) เป็น XML: คำแนะนำของฉันคือ Sun Java Streaming XML Parser Framework (ดูที่นี่ ) ซึ่งอนุญาตให้แยกวิเคราะห์แบบดึงและอนุกรมได้


7

เท่าที่ฉันรู้ไม่มีไลบรารีสำเร็จรูปที่จะทำสิ่งนี้ให้คุณ แต่การสร้างเครื่องมือที่สามารถแปลจาก CSV เป็น XML ควรกำหนดให้คุณเขียนตัวแยกวิเคราะห์ CSV แบบคร่าวๆและเชื่อมต่อ JDOM (หรือไลบรารี XML Java ของคุณ ทางเลือก) ด้วยรหัสกาว


4

ตระกูลโปรเซสเซอร์ Jackson มีแบ็กเอนด์สำหรับข้อมูลหลายรูปแบบไม่ใช่เฉพาะ JSON ซึ่งรวมถึงแบ็กเอนด์XML ( https://github.com/FasterXML/jackson-dataformat-xml ) และ CSV ( https://github.com/FasterXML/jackson-dataformat-csv/ )

การแปลงจะอาศัยอินพุตการอ่านด้วยแบ็กเอนด์ CSV เขียนโดยใช้แบ็กเอนด์ XML วิธีนี้ทำได้ง่ายที่สุดหากคุณมี (หรือสามารถกำหนด) POJO สำหรับรายการต่อแถว (CSV) นี่ไม่ใช่ข้อกำหนดที่เข้มงวดเนื่องจากเนื้อหาจาก CSV อาจถูกอ่านว่า "ไม่ได้พิมพ์" เช่นกัน (ลำดับของStringอาร์เรย์) แต่ต้องทำงานมากขึ้นอีกเล็กน้อยกับเอาต์พุต XML

สำหรับฝั่ง XML คุณจะต้องมีออบเจ็กต์รูทของ wrapper เพื่อให้มีอาร์เรย์หรือListอ็อบเจ็กต์เพื่อทำให้เป็นอนุกรม


3

ฉันมีปัญหาเดียวกันและต้องการแอปพลิเคชันเพื่อแปลงไฟล์ CSV เป็นไฟล์ XML สำหรับหนึ่งในโครงการของฉัน แต่ไม่พบสิ่งใดที่ฟรีและดีพอบนเน็ตดังนั้นฉันจึงเขียนโค้ดแอปพลิเคชัน Java Swing CSVtoXML ของตัวเอง

มันมีอยู่จากเว็บไซต์ของฉันที่นี่ หวังว่ามันจะช่วยคุณได้

ถ้าไม่คุณสามารถเขียนโค้ดของคุณเองได้ง่ายๆเหมือนที่ฉันทำ ซอร์สโค้ดอยู่ภายในไฟล์ jar ดังนั้นให้แก้ไขตามที่คุณต้องการหากไม่ตรงตามความต้องการของคุณ



3

นี่อาจเป็นวิธีแก้ปัญหาพื้นฐานหรือ จำกัด เกินไป แต่คุณไม่สามารถทำString.split()ในแต่ละบรรทัดของไฟล์ได้โดยจดจำอาร์เรย์ผลลัพธ์ของบรรทัดแรกเพื่อสร้าง XML และเพียงแค่คายข้อมูลอาร์เรย์ของแต่ละบรรทัดออกด้วย XML ที่เหมาะสม องค์ประกอบที่เติมการวนซ้ำแต่ละครั้ง?


2
ไม่ใช่ว่าไฟล์ CSV ของคุณเคยมีข้อมูลในเครื่องหมายจุลภาคซึ่งเป็นเรื่องปกติ
Alan Krueger
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.