Java lib hoặc ứng dụng để chuyển đổi tệp CSV sang XML? [đóng cửa]


114

Có ứng dụng hoặc thư viện hiện có trong Java cho phép tôi chuyển đổi CSVtệp dữ liệu thành XMLtệp không?

Các XMLthẻ sẽ được cung cấp thông qua hàng đầu tiên có thể chứa các tiêu đề cột.


47
Có vẻ như đây là câu hỏi đầu tiên với thẻ của Java trong SO.
Paul Vargas

8
@Paul Không chỉ vậy, Nó còn là 123!
bjb568


1
@ bjb568 Ôi. haha

4
Không có gì ngạc nhiên khi bài viết đầu tiên về java trong SO bị đóng lại là lạc đề: D
Sir. Hedgehog

Câu trả lời:


66

Có thể điều này có thể hữu ích: JSefa

Bạn có thể đọc tệp CSV bằng công cụ này và tuần tự hóa nó thành XML.


47

Như những người khác ở trên, tôi không biết bất kỳ cách một bước nào để làm điều đó, nhưng nếu bạn đã sẵn sàng sử dụng các thư viện bên ngoài rất đơn giản, tôi sẽ đề xuất:

OpenCsv để phân tích cú pháp CSV (nhỏ, đơn giản, đáng tin cậy và dễ sử dụng)

Xstream để phân tích cú pháp / tuần tự hóa XML (rất dễ sử dụng và tạo xml hoàn toàn có thể đọc được của con người)

Sử dụng cùng một dữ liệu mẫu như trên, mã sẽ giống như sau:

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

Tạo ra kết quả sau: (Xstream cho phép điều chỉnh rất tốt kết quả ...)

<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

Tôi biết bạn đã yêu cầu Java, nhưng điều này khiến tôi cảm thấy khó chịu vì một nhiệm vụ rất phù hợp với ngôn ngữ kịch bản. Đây là một giải pháp nhanh chóng (rất đơn giản) được viết bằng 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])
            }
        }
    }
}

Viết XML sau thành 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>

Tuy nhiên, mã phân tích cú pháp rất đơn giản (không tính đến dấu phẩy được trích dẫn hoặc thoát) và nó không tính đến dữ liệu có thể vắng mặt.


Vì vậy, bạn có thể gọi một thư viện CSV để thực hiện phân tích cú pháp và sau đó sử dụng trình tạo đánh dấu. Có lẽ bạn có thể chỉnh sửa câu trả lời của mình để hiển thị điều này.
Peter Kelley

18

Tôi có một khung mã nguồn mở để làm việc với CSV và các tệp phẳng nói chung. Có lẽ nó đáng xem: JFileHelpers .

Với bộ công cụ đó, bạn có thể viết mã bằng bean, như:

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

và sau đó chỉ cần phân tích cú pháp các tệp văn bản của bạn bằng cách sử dụng:

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

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

Và bạn sẽ có một bộ sưu tập các đối tượng được phân tích cú pháp.

Hy vọng rằng sẽ giúp!


+1 để sử dụng chú thích. Thật không may, cho đến hôm nay, có vẻ như dự án không có bất kỳ phiên bản mới nào kể từ ngày 28
Stephan

Vâng, tôi đã không có thời gian để tiếp tục phát triển kể từ đó nhưng nó rất ổn định.
kolrie

17

Giải pháp này không cần bất kỳ thư viện CSV hoặc XML nào và tôi biết, nó không xử lý bất kỳ ký tự bất hợp pháp nào và các vấn đề mã hóa, nhưng bạn cũng có thể quan tâm đến nó, miễn là đầu vào CSV của bạn không vi phạm các quy tắc đã đề cập ở trên.

Lưu ý: Bạn không nên sử dụng mã này trừ khi bạn biết mình làm gì hoặc không có cơ hội sử dụng thư viện khác (có thể trong một số dự án quan liêu) ... Sử dụng StringBuffer cho Môi trường Runtime cũ hơn ...

Vì vậy, chúng ta bắt đầu:

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

Đầu vào test.csv (bị đánh cắp từ một câu trả lời khác trên trang này):

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

Kết quả đầu ra:

<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

Sự khác biệt lớn mà JSefa mang lại là nó có thể tuần tự hóa các đối tượng java của bạn thành các tệp CSV / XML / etc và có thể giải mã hóa trở lại các đối tượng java. Và nó được điều khiển bởi các chú thích cho phép bạn kiểm soát nhiều đầu ra.

JFileHelpers cũng có vẻ thú vị.


14

Tôi không hiểu tại sao bạn lại muốn làm điều này. Nó nghe gần giống như mã hóa hàng hóa sùng bái.

Việc chuyển đổi tệp CSV sang XML không thêm bất kỳ giá trị nào. Chương trình của bạn đang đọc tệp CSV, vì vậy việc tranh luận rằng bạn cần XML không hoạt động.

Mặt khác, đọc tệp CSV, làm điều gì đó với các giá trị và sau đó tuần tự hóa sang XML có ý nghĩa (tốt, nhiều như việc sử dụng XML có thể có ý nghĩa ...;)) nhưng bạn được cho là đã có phương tiện tuần tự hóa sang XML.


14

Bạn có thể làm điều này một cách đặc biệt dễ dàng bằng cách sử dụng Groovy và mã rất dễ đọc.

Về cơ bản, biến văn bản sẽ được ghi contacts.xmlcho mỗi dòng trong contactData.csvvà mảng trường chứa mỗi cột.

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 rất đơn giản, nhưng nhìn chung không bao giờ đủ đơn giản đến mức đủ để phân tách trên dấu phẩy.
Alan Krueger,

12

Bạn có thể sử dụng XSLT . Google nó và bạn sẽ tìm thấy một vài ví dụ, chẳng hạn như CSV sang XML Nếu bạn sử dụng XSLT, bạn có thể chuyển đổi XML sang bất kỳ định dạng nào bạn muốn.


8

Ngoài ra còn có thư viện tốt ServingXML của Daniel Parker, có thể chuyển đổi hầu hết mọi định dạng văn bản thuần túy sang XML và ngược lại.

Ví dụ cho trường hợp của bạn có thể được tìm thấy tại đây : Nó sử dụng tiêu đề trường trong tệp CSV làm tên phần tử XML.


7

Không có gì tôi biết có thể làm điều này mà không cần bạn viết một chút mã ... Bạn sẽ cần 2 thư viện riêng biệt:

  • Khung phân tích cú pháp CSV
  • Khung tuần tự hóa XML

Trình phân tích cú pháp CSV mà tôi muốn giới thiệu (trừ khi bạn muốn có một chút thú vị khi viết Trình phân tích cú pháp CSV của riêng mình) là OpenCSV (Dự án SourceForge để phân tích dữ liệu CSV)

Khung tuần tự hóa XML phải là thứ có thể mở rộng quy mô trong trường hợp bạn muốn chuyển đổi tệp CSV lớn (hoặc khổng lồ) sang XML: Đề xuất của tôi là Khung phân tích cú pháp XML của Sun Java Streaming (Xem tại đây ) cho phép phân tích cú pháp kéo VÀ tuần tự hóa.


7

Theo như tôi biết, không có thư viện tạo sẵn nào để làm việc này cho bạn, nhưng việc tạo ra một công cụ có khả năng dịch từ CSV sang XML sẽ chỉ yêu cầu bạn viết một trình phân tích cú pháp CSV thô và kết nối JDOM (hoặc thư viện Java Java của bạn sự lựa chọn) với một số mã keo.


4

Họ bộ xử lý Jackson có các phần phụ trợ cho nhiều định dạng dữ liệu, không chỉ JSON. Điều này bao gồm cả phần phụ trợ XML ( https://github.com/FasterXML/jackson-dataformat-xml ) và CSV ( https://github.com/FasterXML/jackson-dataformat-csv/ ).

Việc chuyển đổi sẽ dựa vào việc đọc đầu vào với phụ trợ CSV, viết bằng phụ trợ XML. Điều này dễ thực hiện nhất nếu bạn có (hoặc có thể xác định) một POJO cho các mục nhập trên mỗi hàng (CSV). Đây không phải là một yêu cầu nghiêm ngặt, vì nội dung từ CSV cũng có thể được đọc "không định kiểu" (một chuỗi các Stringmảng), nhưng đòi hỏi nhiều thao tác hơn trên đầu ra XML.

Đối với phía XML, bạn sẽ cần một đối tượng gốc bao bọc để chứa mảng hoặc Listcác đối tượng để tuần tự hóa.


3

Tôi gặp vấn đề tương tự và cần một ứng dụng để chuyển đổi tệp CSV sang tệp XML cho một trong các dự án của mình, nhưng không tìm thấy bất kỳ thứ gì đủ miễn phí và tốt trên mạng, vì vậy tôi đã viết mã ứng dụng Java Swing CSVtoXML của riêng mình.

Nó có sẵn từ trang web của tôi TẠI ĐÂY . Hy vọng nó sẽ giúp ích cho bạn.

Nếu không, bạn có thể dễ dàng viết mã của riêng mình như tôi đã làm; Mã nguồn nằm bên trong tệp jar, vì vậy hãy sửa đổi nó khi bạn cần nếu nó không đáp ứng yêu cầu của bạn.



3

Điều này có thể quá cơ bản hoặc hạn chế của một giải pháp, nhưng bạn không thể thực hiện String.split()trên mỗi dòng của tệp, ghi nhớ mảng kết quả của dòng đầu tiên để tạo XML và chỉ cần tách dữ liệu mảng của mỗi dòng ra bằng XML thích hợp phần tử đệm mỗi lần lặp của một vòng lặp?


2
Không nếu tệp CSV của bạn từng chứa dấu phẩy được trích dẫn trong dữ liệu, điều này khá phổ biến.
Alan Krueger,
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.