Java lib або додаток для перетворення CSV у XML-файл? [зачинено]


114

Чи існує в Java програма або бібліотека, яка дозволить мені перетворити CSVфайл даних у XMLфайл?

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


47
Здається, це перше питання з тегом Java в SO.
Пол Варгас

8
@Paul Мало того, це ще й 123!
bjb568


1
@ bjb568 О. haha

4
Недарма перший пост для Java в SO був закритий як поза темою: D
Сер. Їжак

Відповіді:


66

Можливо, це може допомогти: JSefa

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


47

Як і інші вище, я не знаю жодного крокового способу зробити це, але якщо ви готові використовувати дуже прості зовнішні бібліотеки, я б запропонував:

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>

27

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

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


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

18

У мене взагалі відкрита рамка для роботи з 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");

І у вас буде колекція проаналізованих об'єктів.

Сподіваюся, що це допомагає!


+1 для використання приміток. На жаль, станом на сьогодні, здається, що проект не має жодної нової версії з 2009-08-11 ...
Stephan

Так, я не встиг продовжувати розвиток з тих пір, але це дуже стабільно.
kolrie

17

Це рішення не потребує жодної бібліотеки 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());

Вхідний тест.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>

15

Велика різниця полягає в тому, що JSefa приносить те, що він може серіалізувати ваші об’єкти java до файлів CSV / XML / тощо та може деріаріалізувати назад до об’єктів java. І це спирається на анотації, які дають вам великий контроль над результатами.

JFileHelpers також виглядає цікаво.


14

Я не розумію, чому ти хотів би це зробити. Це звучить майже як кодування культового культу.

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

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


14

Ви можете зробити це виключно легко, використовуючи 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
CSV простий, але, як правило, ніколи не є простим, щоб розщеплення на коми було достатньо.
Алан Крюгер

12

Ви можете використовувати XSLT . Google це, і ви знайдете кілька прикладів, наприклад, CSV в XML. Якщо ви використовуєте XSLT, ви можете конвертувати XML у потрібний формат.


8

Також є хороша бібліотека ServingXML Daniel Parker, яка здатна конвертувати майже будь-який звичайний текстовий формат у XML і назад.

Приклад для вашого випадку можна знайти тут : Він використовує заголовок поля у файлі CSV як ім'я елемента XML.


7

Нічого я не знаю, що може зробити це без того, щоб принаймні написати трохи коду ... Вам знадобиться 2 окремі бібліотеки:

  • Рамка парсерів CSV
  • Рамка серіалізації XML

Я б рекомендував аналізатор CSV (якщо ви не хочете трохи розважитися, щоб написати свій власний аналізатор CSV) - OpenCSV (проект SourceForge для аналізу даних CSV)

Рамка серіалізації XML повинна бути те, що може масштабуватися у випадку, якщо ви хочете перетворити великий (або величезний) CSV-файл у XML: Моя рекомендація - це тематичний XML-аналізатор парнізації Sun Java (див. Тут ), який дозволяє провести синтаксичний аналіз і серіалізацію.


7

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


4

Сімейство процесорів Джексона містить резервні файли для декількох форматів даних, а не лише 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об'єкти для серіалізації.


3

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

Він доступний з мого веб-сайту ТУТ . Сподіваюся, це допоможе вам.

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



3

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


2
Не якщо ваш файл CSV коли-небудь містить цитовані коми в даних, що є досить поширеним явищем.
Алан Крюгер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.