Có ứng dụng hoặc thư viện hiện có trong Java cho phép tôi chuyển đổi CSV
tệp dữ liệu thành XML
tệp không?
Các XML
thẻ sẽ được cung cấp thông qua hàng đầu tiên có thể chứa các tiêu đề cột.
Có ứng dụng hoặc thư viện hiện có trong Java cho phép tôi chuyển đổi CSV
tệp dữ liệu thành XML
tệp không?
Các XML
thẻ sẽ được cung cấp thông qua hàng đầu tiên có thể chứa các tiêu đề cột.
Câu trả lời:
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>
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.
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!
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>
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ị.
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.
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.xml
cho mỗi dòng trong contactData.csv
và 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>"""
}
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.
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.
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:
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.
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 String
mả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 List
các đối tượng để tuần tự hóa.
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.
Đối với Phần CSV, bạn có thể sử dụng thư viện mã nguồn mở nhỏ của tôi
Đ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?