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
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 * ** * */ 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), false); 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); } } * * John Wayne Marion Robert Morrison male Winterset 156.35 Spiderman Peter Parker male *New York -0.96
Code walkthrough
- A CSVReader is created to read the input CSV file
WriteCsvToXmlUsingFreeMarkerTemplates.csv
. - A TemplateWriter object is created corresponding to the output XML file
WriteCsvToXmlUsingFreeMarkerTemplates.xml
. - The Configuration.setDirectoryForTemplateLoading method is invoked which sets the file system directory from which to load templates.
- The header,footer and detail template are set using the setHeaderTemplate, setFooterTemplate and setDetailTemplate respectively.
- 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>