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

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

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

16 ответов

Решение

Может быть, это может помочь: 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>

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

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

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

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

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

Вы можете сделать это исключительно легко, используя Groovy, и код очень удобочитаемый.

В основном, текстовая переменная будет записана в contacts.xml для каждой строки в contactData.csv, а массив fields содержит каждый столбец.

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 в любой формат, какой захотите.

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

  • CSV Parser Framework
  • Структура XML-сериализации

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

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

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

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

Насколько я знаю, нет готовой библиотеки, которая могла бы сделать это для вас, но для создания инструмента, способного переводить из 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 вы можете использовать мою маленькую библиотеку с открытым исходным кодом

Другие вопросы по тегам