In meinem letzten Beitrag habe ich AutoCopy vorgestellt. Eine Java-Applikation, die es ermöglicht, automatisch Dateien von einem zu überwachenden Ort zum anderen zu verschieben.

Heute möchte ich zeigen, wie einfach es in Java 8 ist, einen CSV nach XML Konverter zu schreiben und stelle eine kleine CLI und JavaFX-Applikation vor.

Von CSV nach XML mittels Streams

In gerade einmal 18 Zeilen ist es in Java 8 möglich einen CSV to XML Converter zu schreiben. Wie im folgenden Code zu sehen, wird dies durch die funktionale Programmierung und den Einsatz von Streams möglich:

public static String toXML(List<String> inputLines, String delim) {
    List<String> header = new ArrayList<>(Arrays.asList(inputLines.get(0).split(delim)));
    String output = "<lines>" + inputLines.stream().skip(1)
            .map(line -> {
                List<String> cells = Arrays.asList(line.split(delim));
                return "<line>" + IntStream.range(0, cells.size())
                        .mapToObj(i -> "<" + header.get(i) + ">" + cells.get(i) + "</" + header.get(i) + ">")
                        .collect(Collectors.joining())
                        + "</line>";
            })
            .collect(Collectors.joining(System.lineSeparator()))
            .replaceAll("&", "&amp;")
            + "</lines>";
    return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
            + System.lineSeparator()
            + output
            + System.lineSeparator();
}

Diese Methode erwartet als ersten Parameter, die Zeilen in Form einer Liste. Hier kann bspw Files.readAllLines(Path) verwendet werden, um eine Datei entsprechend auszulesen. Der zweite Parameter ist das Trennzeichen. Bei CSV-Dateien üblicherweise ein Komma. Bei CSV-Exports aus Microsoft Excel sieht man allerdings auch gerne ein Semikolon.

Zunächst wird die erste Zeile der CSV-Datei als Headerinformation gespeichert. Aus diesen Informationen werden später die einzelnen XML-Tags generiert. Der möglicherweise erklärungsbedürftigste Teil ist die anonyme Funktion, die in map ausgeführt wird. Wie auch bei der ersten Zeile werden die nachfolgenden Zeilen am Trennzeichen getrennt. Um auf die korrekten Header zuzugreifen, verwende ich einen IntStream, der mir eine Sequenz von Zahlen liefert. In diesem Fall von 0 bis zur Gesamtanzahl der Zellen in einer Zeile. Hier nutze ich die Tatsache aus, dass die einzelnen Zellen der Zeilen logischerweise die selben Headerzellen besitzen. Mit Hilfe der IntStream-Methode mapToObj wird die aktuelle Zahl des Streams durch eine Zeichenkette, konkret durch einen XML-Tag mit Inhalt ersetzt.

Während die Elemente des IntStreams ohne ein spezielles Trennzeichen zu einem String zusammengefügt werden (collect(Collectors.joining())), werden die Elemente des inputList-Streams in jeweils eine einzelne Zeile geschrieben .collect(Collectors.joining(System.lineSeparator())).

Um einen validen XML-Code zu erzeugen, repräsentiert der XML-Tag line eine Zeile und der Tag lines das root-Element der XML-Datei. Weiterhin werden spezielle Sonderzeichen durch ihre XML-Entitäten ersetzt sowie ein XML-Header geschrieben. Der nun zurückgegebene String dieser Methode, kann bspw mit Hilfe von Files.write in eine Datei geschrieben werden.

Beispiel

Nach etwas trockener Theorie folgt ein kurzes Beispiel. Der vorgestellte Quellcode generiert aus dieser CSV-Datei:

vorname,name,alter
heinz,mustermann,39
peter,pan,12
Pippi,Langstrumpf,10

folgende XML-Datei:

<?xml version="1.0" encoding="UTF-8"?>
<lines><line><vorname>heinz</vorname><name>mustermann</name><alter>39</alter></line>
<line><vorname>peter</vorname><name>pan</name><alter>12</alter></line>
<line><vorname>Pippi</vorname><name>Langstrumpf</name><alter>10</alter></line></lines>

JavaFX-GUI

Um dieses kleine 18-zeilige Konstrukt habe ich eine kleine GUI auf Basis von JavaFX gebaut, die aus drei wesentlichen Elementen besteht: Ein Eingabefeld, in der die CSV-Datei eingetragen wird, ein Trennzeichen und ein Ausgabefeld, in der der Ausgabepfad ausgewählt wird.

CSV to XML Converter

Im Gegensatz zur toXML-Methode gibt es zum JavaFX-Quellcode nichts spannendes zu erzählen. Hier verweise ich am besten direkt - wie auch bei meinen vorherigen Tools - auf mein GitHub-Repository, in dem sich neben der ausführbaren Jar-Datei, auch der Quellcode des CSV to XML Converters finden lässt.

CLI-Client

Ein nennenswertes Feature des CSV to XML Converters ist das es neben der JavaFX-GUI, auch auf der Kommandozeile verwendet werden kann. Sozusagen ein CLI-Client. Wie sich das relativ trival umsetzen lässt, zeigt die Main-Methode des Konverters:

public static void main(String... args) throws Exception {
    if (args.length < 3) {
        Application.launch(App.class, args); // start GUI
        return;
    }

    Path output = Paths.get(args[0]);
    Path input = Paths.get(args[1]);
    String delim = args[2];
    List<String> lines = Files.readAllLines(input);
    Files.write(output, CSV.toXML(lines, delim).getBytes());
}

Falls weniger als drei Aufrufparameter übergeben wurden, wird der CLI-Client ausgeführt, ansonsten die JavaFX Oberfläche. Natürlich ist dieser CLI-Client sehr einfach gehalten ohne jegliche Fehlerüberprüfungen.

blogroll
tags