Сведения о вопросе

Htmlщик

16:03, 1st July, 2020

Теги

java   xml   csv   data-conversion    

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

Просмотров: 593   Ответов: 16

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

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



  Сведения об ответе

+-*/

18:03, 1st July, 2020

Может быть, это поможет: JSefa

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


  Сведения об ответе

ЯЯ__4

18:03, 1st July, 2020

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

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>


  Сведения об ответе

ЯЯ__4

18:03, 1st July, 2020

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

<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>

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


  Сведения об ответе

qwerty101

18:03, 1st July, 2020

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

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

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

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

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


  Сведения об ответе

SILA

18:03, 1st July, 2020

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


  Сведения об ответе

P_S_S

18:03, 1st July, 2020

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

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


  Сведения об ответе

прога

18:03, 1st July, 2020

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

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

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


  Сведения об ответе

PHPH

18:03, 1st July, 2020

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


  Сведения об ответе

VERSUION

18:03, 1st July, 2020

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


  Сведения об ответе

SSESION

18:03, 1st July, 2020

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

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


  Сведения об ответе

park

18:03, 1st July, 2020

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


  Сведения об ответе

prince

18:03, 1st July, 2020

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

  • Парсер CSV Рамках
  • Платформа Сериализации XML

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

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


  Сведения об ответе

ЯЯ__4

18:03, 1st July, 2020

Семейство процессоров Jackson имеет бэкенды для нескольких форматов данных, а не только JSON. Это включает в себя как XML ( https://github.com/FasterXML/jackson-dataformat-xml), так и CSV (https://github.com/FasterXML/jackson-dataformat-csv/ ) бэкенды.

Преобразование будет опираться на значение входного сигнала с CSV бэкэнд, пишите через XML серверной. Это проще всего сделать, если у вас есть (или вы можете определить) POJO для каждой строки (CSV) записей. Это не является строгим требованием, так как содержимое из CSV также может быть прочитано "untyped" (последовательность массивов String ), но требует немного больше работы на выходе XML.

Для XML стороны вам понадобится корневой объект-оболочка, чтобы содержать массив или List объектов для сериализации.


  Сведения об ответе

$DOLLAR

18:03, 1st July, 2020

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


  Сведения об ответе

+-*/

18:03, 1st July, 2020

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


  Сведения об ответе

lourence

18:03, 1st July, 2020

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

Он доступен с моего сайта HERE . Надеюсь, это вам поможет.

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться