Есть ли на 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-код в стандартный вывод:
<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 .
С помощью этого набора инструментов вы можете писать код с использованием bean-компонентов, например:
@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());
Входной 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>
Большое различие заключается в том, что JSefa предоставляет возможность сериализовать ваши java-объекты в файлы CSV / XML / etc и может десериализовать их обратно в 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 . Погуглите, и вы найдете несколько примеров, например, CSV в XML. Если вы используете XSLT, вы можете преобразовать XML в любой формат, который вам нужен.
Также существует хорошая библиотека ServingXML от Дэниела Паркера, которая способна преобразовывать практически любой простой текстовый формат в XML и обратно.
Пример для вашего случая можно найти здесь : он использует заголовок поля в файле CSV в качестве имени элемента XML.
Я не знаю ничего, что могло бы сделать это без того, чтобы вы хотя бы написали немного кода ... Вам понадобятся 2 отдельные библиотеки:
Я бы порекомендовал парсер CSV (если вы не хотите немного повеселиться, чтобы написать свой собственный парсер CSV) - это OpenCSV (проект SourceForge для анализа данных CSV).
Платформа XML-сериализации должна быть чем-то, что может масштабироваться в случае, если вы хотите преобразовать большой (или огромный) CSV-файл в XML: Я рекомендую Sun Java Streaming XML Parser Framework (см. Здесь ), которая позволяет выполнять анализ методом извлечения и сериализацию.
Семейство процессоров 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 вам потребуется корневой объект оболочки, содержащий массив или List
объекты для сериализации.
У меня была та же проблема, и мне требовалось приложение для преобразования файла CSV в файл XML для одного из моих проектов, но я не нашел в сети ничего бесплатного и достаточно хорошего, поэтому я написал свое собственное приложение Java Swing CSVtoXML.
Он доступен на моем сайте ЗДЕСЬ . Надеюсь, это поможет вам.
Если нет, вы можете легко написать свой собственный код, как это сделал я; Исходный код находится внутри файла jar, поэтому измените его по своему усмотрению, если он не соответствует вашим требованиям.
Для части CSV вы можете использовать мою небольшую библиотеку с открытым исходным кодом
Это может быть слишком простым или ограниченным решением, но не могли бы вы сделать для String.split()
каждой строки файла, запомнив массив результатов первой строки для генерации XML, и просто выплюнуть данные массива каждой строки с правильным XML элементы, заполняющие каждую итерацию цикла?