Java-библиотека или приложение для преобразования CSV в файл XML?

Существует ли существующее приложение или библиотека на Java, которые позволят мне преобразовать CSV файл данных в XML файл?

Теги XML будут предоставлены, возможно, через первую строку, содержащую заголовки столбцов.


person A Salim    schedule 01.08.2008    source источник
comment
Кажется, это первый вопрос с тегом Java в SO.   -  person Paul Vargas    schedule 13.09.2013
comment
@Paul Мало того, это еще и 123!   -  person bjb568    schedule 22.02.2014
comment
@ bjb568 Что ты имеешь в виду?   -  person    schedule 09.07.2017
comment
@Tommy stackoverflow.com/q/123   -  person bjb568    schedule 10.07.2017
comment
@bjb568 О. ха-ха   -  person    schedule 10.07.2017
comment
Просто введите номер 123 вопроса в URL-адресе и найдите этот вопрос, который дает + 1 к ответу и вопросу. Спасибо!   -  person Nadeem    schedule 20.12.2018
comment
Неудивительно, что первый пост о java в SO был закрыт как не по теме: D   -  person Sir. Hedgehog    schedule 08.03.2019
comment
вау это было 11 лет назад   -  person larsaars    schedule 09.06.2020


Ответы (16)


Возможно, это может помочь: JSefa

С помощью этого инструмента вы можете прочитать файл CSV и сериализовать его в XML.

person svrist    schedule 01.08.2008

Как и другие выше, я не знаю одношагового способа сделать это, но если вы готовы использовать очень простые внешние библиотеки, я бы предложил:

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>
person Laurent K    schedule 10.09.2008

Я знаю, что вы просили 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>

Однако код выполняет очень простой синтаксический анализ (без учета кавычек или экранированных запятых) и не учитывает возможные отсутствующие данные.

person Anthony Cramp    schedule 09.08.2008
comment
Таким образом, вы можете вызвать библиотеку CSV для анализа, а затем использовать построитель разметки. Возможно, вы могли бы отредактировать свой ответ, чтобы показать это. - person Peter Kelley; 01.10.2008

У меня есть фреймворк с открытым исходным кодом для работы с 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");

И у вас будет коллекция проанализированных объектов.

Надеюсь, это поможет!

person kolrie    schedule 27.09.2008
comment
+1 за использование аннотаций. К сожалению, на сегодняшний день кажется, что у проекта нет новой версии с 2009-08-11... - person Stephan; 12.11.2012
comment
Да, с тех пор у меня не было времени продолжать разработку, но она очень стабильна. - person kolrie; 12.11.2012

Этому решению не нужны никакие библиотеки 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>
person Martin Klinke    schedule 21.08.2008

Я не понимаю, почему вы хотите это сделать. Звучит почти как кодирование карго-культа.

Преобразование файла CSV в XML не добавляет никакой ценности. Ваша программа уже читает CSV-файл, поэтому утверждение, что вам нужен XML, не работает.

С другой стороны, чтение CSV-файла, выполнение нечто со значениями, а затем сериализация в XML имеет смысл (настолько же, насколько может иметь смысл использование XML... ;)) но вы предположительно уже имел бы средства сериализации в XML.

person Ryan Fox    schedule 01.08.2008

Большая разница заключается в том, что JSefa может сериализовать ваши Java-объекты в CSV/XML/ etc файлы и могут десериализоваться обратно в java-объекты. И это управляется аннотациями, которые дают вам большой контроль над выводом.

JFileHelpers тоже выглядит интересно.

person James Selvakumar    schedule 11.08.2010

Вы можете сделать это исключительно легко, используя 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>"""
}
person abarax    schedule 02.10.2008
comment
CSV прост, но, как правило, он никогда не бывает настолько простым, чтобы было достаточно разделения запятой. - person Alan Krueger; 07.07.2010

Вы можете использовать XSLT. Погуглите, и вы найдете несколько примеров, например. CSV в XML Если вы используете XSLT затем вы можете преобразовать XML в любой формат, который вы хотите.

person Simmo    schedule 16.10.2008

Также есть неплохая библиотека ServingXML Дэниела Паркера, которая способна конвертировать почти любой простой текстовый формат в XML и обратно. .

Пример для вашего случая можно найти здесь: используется заголовок поля в CSV. файл в качестве имени элемента XML.

person Lukáš Rampa    schedule 30.09.2008

Я ничего не знаю о том, что может сделать это без того, чтобы вы хотя бы написали немного кода... Вам понадобятся 2 отдельные библиотеки:

  • Платформа парсера CSV
  • Платформа XML-сериализации

Парсер CSV, который я бы порекомендовал (если вы не хотите немного повеселиться, написав свой собственный парсер CSV), — это OpenCSV (проект SourceForge для анализа данных CSV).

Структура XML-сериализации должна быть чем-то масштабируемым, если вы хотите преобразовать большой (или огромный) CSV-файл в XML: я рекомендую Sun Java Streaming XML Parser Framework (см. здесь), что позволяет осуществлять разбор по запросу и сериализацию.

person Claude Houle    schedule 04.08.2008

Насколько я знаю, нет готовой библиотеки, которая сделает это за вас, но создание инструмента, способного переводить из CSV в XML, потребует от вас только написать грубый синтаксический анализатор CSV и подключить JDOM (или вашу библиотеку XML Java для выбор) с некоторым связующим кодом.

person Matt    schedule 02.08.2008

Семейство процессоров 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 объектов для сериализации.

person StaxMan    schedule 29.04.2015

Это может быть слишком простым или ограниченным решением, но не могли бы вы сделать String.split() в каждой строке файла, запоминая результирующий массив первой строки для создания XML, и просто выводите данные массива каждой строки с помощью правильные элементы XML, заполняющие каждую итерацию цикла?

person saint_groceon    schedule 01.08.2008
comment
Нет, если ваш файл CSV когда-либо содержит запятые в кавычках в данных, что довольно часто. - person Alan Krueger; 07.07.2010

У меня была та же проблема, и мне нужно было приложение для преобразования файла CSV в файл XML для одного из моих проектов, но я не нашел ничего бесплатного и достаточно хорошего в сети, поэтому я написал свое собственное приложение Java Swing CSVtoXML.

Он доступен на моем веб-сайте ЗДЕСЬ. Надеюсь, это поможет вам.

Если нет, вы можете легко написать свой собственный код, как это сделал я; Исходный код находится внутри файла jar, поэтому измените его по мере необходимости, если он не соответствует вашим требованиям.

person Ibrabel    schedule 16.04.2014

Для части CSV вы можете использовать мою небольшую библиотеку с открытым исходным кодом

person Arne Burmeister    schedule 16.09.2008