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

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

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

Ответ 1

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

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

Ответ 2

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

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>

Ответ 3

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

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

Ответ 4

У меня есть среда с открытым исходным кодом для работы с CSV и плоскими файлами в целом. Возможно, стоит посмотреть: JFileHelpers.

С помощью этого инструментария вы можете написать код с помощью beans, например:

@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");

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

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

Ответ 5

Это решение не нуждается в каких-либо 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>

Ответ 6

Вы можете сделать это исключительно легко, используя 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>"""
}

Ответ 7

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

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

Ответ 8

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

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

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

Ответ 9

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

Ответ 10

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

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

Ответ 11

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

Ответ 12

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

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

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

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

Ответ 13

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

Ответ 15

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

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

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

Ответ 16

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