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