Чи існує в Java програма або бібліотека, яка дозволить мені перетворити CSV
файл даних у XML
файл?
Ці XML
мітки будуть надані через , можливо , перший рядок , що містить заголовки стовпців.
Чи існує в Java програма або бібліотека, яка дозволить мені перетворити CSV
файл даних у XML
файл?
Ці XML
мітки будуть надані через , можливо , перший рядок , що містить заголовки стовпців.
Відповіді:
Як і інші вище, я не знаю жодного крокового способу зробити це, але якщо ви готові використовувати дуже прості зовнішні бібліотеки, я б запропонував:
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>
Я знаю, що ви просили 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>
Однак код робить дуже простий аналіз (без урахування котируваних чи уникнутих коми) і не враховує можливих відсутніх даних.
У мене взагалі відкрита рамка для роботи з CSV та плоскими файлами. Можливо, це варто подивитися: 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");
І у вас буде колекція проаналізованих об'єктів.
Сподіваюся, що це допомагає!
Це рішення не потребує жодної бібліотеки 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());
Вхідний тест.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>
Велика різниця полягає в тому, що JSefa приносить те, що він може серіалізувати ваші об’єкти java до файлів CSV / XML / тощо та може деріаріалізувати назад до об’єктів java. І це спирається на анотації, які дають вам великий контроль над результатами.
JFileHelpers також виглядає цікаво.
Я не розумію, чому ти хотів би це зробити. Це звучить майже як кодування культового культу.
Перетворення CSV-файлу в XML не додає жодного значення. Ваша програма вже читає файл CSV, тому аргументація того, що вам потрібен XML, не працює.
З іншого боку, читати файл CSV, робити щось із значеннями, а потім серіалізувати в XML має сенс (ну, так як використання XML може мати сенс ...;)), але ви, мабуть, уже маєте засоби для серіалізація до XML.
Ви можете зробити це виключно легко, використовуючи 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>"""
}
Ви можете використовувати XSLT . Google це, і ви знайдете кілька прикладів, наприклад, CSV в XML. Якщо ви використовуєте XSLT, ви можете конвертувати XML у потрібний формат.
Також є хороша бібліотека ServingXML Daniel Parker, яка здатна конвертувати майже будь-який звичайний текстовий формат у XML і назад.
Приклад для вашого випадку можна знайти тут : Він використовує заголовок поля у файлі CSV як ім'я елемента XML.
Нічого я не знаю, що може зробити це без того, щоб принаймні написати трохи коду ... Вам знадобиться 2 окремі бібліотеки:
Я б рекомендував аналізатор CSV (якщо ви не хочете трохи розважитися, щоб написати свій власний аналізатор CSV) - OpenCSV (проект SourceForge для аналізу даних CSV)
Рамка серіалізації XML повинна бути те, що може масштабуватися у випадку, якщо ви хочете перетворити великий (або величезний) CSV-файл у XML: Моя рекомендація - це тематичний XML-аналізатор парнізації Sun Java (див. Тут ), який дозволяє провести синтаксичний аналіз і серіалізацію.
Сімейство процесорів Джексона містить резервні файли для декількох форматів даних, а не лише 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 вам знадобиться кореневий об'єкт обгортки, який містить масив або List
об'єкти для серіалізації.
У мене була така ж проблема, і мені потрібна була програма для перетворення CSV-файлу у XML-файл для одного з моїх проектів, але в мережі я не знайшов нічого вільного і достатньо хорошого, тому я зашифрував власний додаток Java Swing CSVtoXML.
Він доступний з мого веб-сайту ТУТ . Сподіваюся, це допоможе вам.
Якщо ні, ви можете легко кодувати свій власний, як я; Вихідний код знаходиться у файлі jar, тому змініть його, як вам потрібно, якщо він не заповнить вашу вимогу.
Для частини CSV ви можете використовувати мою маленьку бібліотеку з відкритим кодом
Це може бути занадто базовим або обмеженим рішенням, але ви не могли зробити це String.split()
у кожному рядку файлу, запам'ятовуючи масив результатів першого рядка для створення XML і просто виплюнуючи дані масиву кожного рядка за допомогою належного XML елементи набивання кожної ітерації петлі?