Examples >

Write CSV To XML Using FreeMarker Templates

This example shows you how to write the contents of a CSV file to an XML file in Java via freemarker templates using the CSVReader and TemplateWriter classes. FreeMarker is a "template engine"; a generic tool to generate text output based on templates.

This example can also be modified to show how to write java objects to XML using freemarker templates.

Input CSV file

stageName, realName, gender, city, balance
John Wayne, Marion Robert Morrison, male, Winterset, 156.35
Spiderman, Peter Parker, male, New York, -0.96

Java code

/*
 * Copyright (c) 2006-2018 North Concepts Inc.  All rights reserved.
 * Proprietary and Confidential.  Use is subject to license terms.
 *
 * http://northconcepts.com/data-pipeline/licensing/
 *
 */
package com.northconcepts.datapipeline.examples.cookbook;

import java.io.File;
import java.io.FileWriter;

import com.northconcepts.datapipeline.core.DataReader;
import com.northconcepts.datapipeline.csv.CSVReader;
import com.northconcepts.datapipeline.job.Job;
import com.northconcepts.datapipeline.template.TemplateWriter;

public class WriteCsvToXmlUsingFreeMarkerTemplates {

    /*
     * Produces the following XML
     * 
     * <?xml version="1.0" encoding="UTF-8" standalone="no"?> <records> <record> <field name="stageName">John Wayne</field> <field
     * name="realName">Marion Robert Morrison</field> <field name="gender">male</field> <field name="city">Winterset</field> <field
     * name="balance">156.35</field> </record>
     * 
     * <record> <field name="stageName">Spiderman</field> <field name="realName">Peter Parker</field> <field name="gender">male</field>
     * <field name="city">New York</field> <field name="balance">-0.96</field> </record> </records>
     * 
     * 
     */

    public static void main(String[] args) throws Throwable {
        String in = "example/data/input/WriteCsvToXmlUsingFreeMarkerTemplates.csv";
        String out = "example/data/output/WriteCsvToXmlUsingFreeMarkerTemplates.xml";

        DataReader reader = new CSVReader(new File(in)).setFieldNamesInFirstRow(true);

        TemplateWriter writer = new TemplateWriter(new FileWriter(out));
        writer.setFieldNamesInFirstRow(false);
        writer.getConfiguration().setDirectoryForTemplateLoading(new File("example/data/input"));
        writer.setHeaderTemplate("WriteAnXmlFileUsingFreeMarkerTemplates-header-2.xml");
        writer.setFooterTemplate("WriteAnXmlFileUsingFreeMarkerTemplates-footer-2.xml");
        writer.setDetailTemplate("WriteAnXmlFileUsingFreeMarkerTemplates-detail-2.xml");

        Job.run(reader, writer);
    }

}

Code walkthrough

  1. A CSVReader is created to read the input CSV file WriteCsvToXmlUsingFreeMarkerTemplates.csv.
  2. A TemplateWriter object is created corresponding to the output XML file WriteCsvToXmlUsingFreeMarkerTemplates.xml.
  3. The Configuration.setDirectoryForTemplateLoading method is invoked which sets the file system directory from which to load templates.
  4. The header,footer and detail template are set using the setHeaderTemplate, setFooterTemplate and setDetailTemplate respectively.
  5. Data is transferred from the input CSV file to the output XML file via JobTemplate.DEFAULT.transfer method.

CSVReader

CSVReader is an input reader which can be used to read CSV files. It is a sub-class of TextReader and inherits the open and close among other methods. The CSVReader.setFieldNamesInFirstRow(true) method causes the CSVReader to use the names specified in the first row of the input data as field names. If this method is not invoked, the fields would be named as A1, A2, etc. similar to MS Excel. If those fields names need to be changed, a rename transformation can be added on top of CSVReader or any other type (Refer Rename a field for example).

TemplateWriter

A TemplateWriter class can be used to create an output file based on freemarker templates. It is a sub-class of TextWriter.html and overrides the open and close among other methods. Its setFieldNamesInFirstRow method can be used to specify whether the field names should be used in the first row or not. So if invoked with a true value, an additional row will be created in the output XML with the field names.

The getConfiguration method returns a Configuration object from FreeMarker API which can be used to set the file system directory from which to load templates via Configuration.setDirectoryForTemplateLoading method. Setter methods are defined to set the file paths of the header, footer and detail freemarker templates. These templates are then used by the freemarker API to generate the Header, body and footer of the output XML file as detailed below.

FreeMarker Templates

Three FreeMarker templates are used together to generate XML: header, detail, and footer.

Header

The header template (WriteAnXmlFileUsingFreeMarkerTemplates-header-2.xml) contains the XML declaration and opening tags.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<records>

Detail

The detail template (WriteAnXmlFileUsingFreeMarkerTemplates-detail-2.xml) contains the FreeMarker code to convert each record to XML. Note that this template is invoked once for every record in the input. Each row in the CSV file is mapped to a Record object. The freemarker code loops through all the fields of the Record, outputs the field name and the field value. The field value is obtained via the Record.getField("fieldName").getValue method

	<record>
		<#list record.fieldNames as fieldName>
		<field name="${fieldName}">${record.getField(fieldName).getValue()}</field>
		</#list>
	</record>

Footer

The footer template (WriteAnXmlFileUsingFreeMarkerTemplates-footer-2.xml) contains the closing XML tags.

</records>

Output XML

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<records>
    <record>
        <field name="stageName">John Wayne</field>
        <field name="realName">Marion Robert Morrison</field>
        <field name="gender">male</field>
        <field name="city">Winterset</field>
        <field name="balance">156.35</field>
    </record>

    <record>
        <field name="stageName">Spiderman</field>
        <field name="realName">Peter Parker</field>
        <field name="gender">male</field>
        <field name="city">New York</field>
        <field name="balance">-0.96</field>
    </record>
</records>
Mobile Analytics