Есть ли в Ява существующее приложение или библиотека, которые позволят мне преобразовать файл данных CSV в файл XML?
Теги XML могут быть предоставлены через, возможно, первую строку, содержащую заголовки столбцов.
@Paul Мало того, это еще 123!
@ bjb568 Что ты имеешь в виду?
@Tommy stackoverflow.com/q/123
@ bjb568 О. ха-ха
Просто введите 123 вопроса № в URL-адресе и вы пришли к этому вопросу, который дает +1 к ответу и вопросу. Спасибо!
Неудивительно, что первый пост для java в SO был закрыт как не по теме: D
вау, это было 11 лет назад




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