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

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

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

Ответов (16)

Решение

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

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

Я знаю, что вы просили 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-файла в XML-файл для одного из моих проектов, но я не нашел ничего бесплатного и достаточно хорошего в сети, поэтому я написал свое собственное приложение Java Swing CSVtoXML.

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

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

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

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

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

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

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

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

  • Фреймворк парсера CSV
  • Платформа сериализации XML

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

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

Это решение не требует каких-либо библиотек 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");

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

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

Также существует хорошая библиотека 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>"""
}

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

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

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

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