Write an XML File using FreeMarker Templates
This example uses TemplateWriter and FreeMarker to generate XML. The TemplateWriter approach uses little overhead and can be used to generate huge XML files (or output streams).
XML Output
The XML resulting from this example will look like the following (line breaks added for clarity).
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <actors> <north-america> <actor stage-name="John Wayne" real-name="Marion Robert Morrison"> <gender>male</gender> <city>Winterset</city> <balance>156.35</balance> </actor> <actor stage-name="Spiderman" real-name="Peter Parker"> <gender>male</gender> <city>New York</city> </actor> </north-america> </actors>
Java Code
The code creates an in-memory reader as the datasource with two records. This can easily be changed to read from a database if needed.
Next we create the TemplateWriter and set the root folder for loading templates along with the header, footer, and detail templates.
package com.northconcepts.datapipeline.examples.cookbook; import java.io.File; import java.io.FileWriter; import com.northconcepts.datapipeline.core.Record; import com.northconcepts.datapipeline.core.RecordList; import com.northconcepts.datapipeline.job.Job; import com.northconcepts.datapipeline.memory.MemoryReader; import com.northconcepts.datapipeline.template.TemplateWriter; public class WriteAnXmlFileUsingFreeMarkerTemplates { /* * Produces the following XML (line breaks added for clarity) * ** */ public static void main(String[] args) throws Throwable { Record record1 = new Record(); record1.getField("stageName", true).setValue("John Wayne"); record1.getField("realName", true).setValue("Marion Robert Morrison"); record1.getField("gender", true).setValue("male"); record1.getField("city", true).setValue("Winterset"); record1.getField("balance", true).setValue(156.35); Record record2 = new Record(); record2.getField("stageName", true).setValue("Spiderman"); record2.getField("realName", true).setValue("Peter Parker"); record2.getField("gender", true).setValue("male"); record2.getField("city", true).setValue("New York"); record2.getField("balance", true).setValue(-0.96); MemoryReader reader = new MemoryReader(new RecordList(record1, record2)); TemplateWriter writer = new TemplateWriter(new FileWriter("example/data/output/credit-balance-04.xml")); writer.setFieldNamesInFirstRow(false); writer.getConfiguration().setDirectoryForTemplateLoading(new File("example/data/input")); writer.setHeaderTemplate("WriteAnXmlFileUsingFreeMarkerTemplates-header.xml"); writer.setFooterTemplate("WriteAnXmlFileUsingFreeMarkerTemplates-footer.xml"); writer.setDetailTemplate("WriteAnXmlFileUsingFreeMarkerTemplates-detail.xml"); Job.run(reader, writer); } } male Winterset 156.35 male New York
FreeMarker Templates
Three FreeMarker templates will be used together to generate XML: header, detail, and footer.
Header
The header template (WriteAnXmlFileUsingFreeMarkerTemplates-header.xml) contains the XML declaration and opening tags.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <actors> <north-america>
Detail
The detail template (WriteAnXmlFileUsingFreeMarkerTemplates-detail.xml) contains the FreeMarker code to convert each record to XML. Each field's value is automatically added to the template's model and can be used by referencing its name. The template also includes a record
variable of type com.northconcepts.datapipeline.core.Record that can also be referenced if needed.
<actor stage-name="${stageName}" real-name="${realName}"> <gender>${gender}</gender> <city>${city}</city> <#if (balance >= 0)> <balance>${balance}</balance> </#if> </actor>
Footer
The footer template (WriteAnXmlFileUsingFreeMarkerTemplates-footer.xml) contains the closing XML tags.
</north-america> </actors>