Friday, March 25, 2016

FreeMarker Template Engine With XML Data Model.

On previous post we learn how to marge object type data model with FreeMarker template. Now we learn how we can marge FreeMarker template with  XML data model. All steps are basically same as Object Data binding with FreeMarker except datamodel creation. Here we put the complete xml file into the map. We discuss in details in below

Step: 1
Download the latest stable Fremarker version from here.

Step: 2
Extract the downloaded folder and put the the jar in our project.

Step:3
Create Fremarker configuration object with version number and some recommend settings.
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setLocale(Locale.US);
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);


Step:4
Mentioning the template file location.

        cfg.setDirectoryForTemplateLoading(new File("./resources"));
        Template template = cfg.getTemplate("xml_Freemarker_Template.ftl");


Step: 5 
Creating Data model part.
         Map xmlData = new HashMap();
         xmlData.put("samples", freemarker.ext.dom.NodeModel.parse(new File("./resources/sampleXML.xml")));

Here we put key as "samples" basically we set the root of the xml document we can mention any name here but we need to put the same name in .ftl file also.   

Step: 6 
 Creating the output part.

  This is for console output:

        Writer consoleWriter = new OutputStreamWriter(System.out);
        template.process(xmlData, consoleWriter);


  This is for html output:     

        try (Writer fileWriter = new FileWriter(new File("output.html"))) {
            template.process(xmlData, fileWriter);
        }


Step: 7
Creating template file and save it with .ftl extention. Here it is a sample template file.

<#ftl strip_whitespace = true>

<#assign charset="UTF-8">
<#assign title="Example">
<#assign content>
This is content
</#assign>
<!DOCTYPE html>
<html>
    <head>
        <title>${title}</title>
        <meta charset="${charset}">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        </head>
    <body> 

        <!-- We need to use the same name of the root element which is set from code.
        Here it is "samples" and then follow the xml path so it is
sample.sampledata--> 
        <#foreach sample in samples.sample.sampledata>
            <div>
                id:${sample.id}
                name: ${sample.name}
                age:${sample.age}
                salary:${sample.salary}
                exp:${sample.exp}
                sex:${sample.sex}
                <#foreach address in sample.addresses>
                <div>
                    address1:${address.address1}
                    <#if "${address.address2}"!="">
                    address1:${address.address2}
                    </#if>
                </div>
                </#foreach>
            </div> 
        </#foreach>
        </body>
    </html>


Step: 8  

Sample XML File.

<sample>
    <sampledata>
        <id>1</id>
        <name>TestName1</name>
        <age>28</age>
        <salary>50000</salary>
        <exp>6.6</exp>
        <sex>m</sex>
        <addresses>
            <address1>My Address1</address1>
            <address2></address2>
        </addresses>
    </sampledata>


 Complete code given below :

Main Class :

package freemarker;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;

public class FreemarkerXML {

    public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException, TemplateException {
        /**
         * Create Fremarker configuration object with version number and some
         * recommend settings.
         */

        Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setLocale(Locale.US);
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

        /**
         * Mentioning the template file location.
         */

        cfg.setDirectoryForTemplateLoading(new File("./resources"));
        Template template = cfg.getTemplate("xml_Freemarker_Template.ftl");
        Map xmlData = new HashMap();
      
        /**
         * Read the XML file and process the template using FreeMarker.
         */

        xmlData.put("samples", freemarker.ext.dom.NodeModel.parse(new File("./resources/sampleXML.xml")));

        /**
         * Creating the output part.
         */

        Writer consoleWriter = new OutputStreamWriter(System.out);
        template.process(xmlData, consoleWriter);

        /**
         * For the sake of example, also write output into a file.
         */

        try (Writer fileWriter = new FileWriter(new File("output.html"))) {
            template.process(xmlData, fileWriter);
        }
    }
}


Sample XML:

<sample>
    <sampledata>
        <id>1</id>
        <name>TestName1</name>
        <age>28</age>
        <salary>50000</salary>
        <exp>6.6</exp>
        <sex>m</sex>
        <addresses>
            <address1>My Address1</address1>
            <address2></address2>
        </addresses>
    </sampledata>
    <sampledata>
        <id>2</id>
        <name>TestName2</name>
        <age>26</age>
        <salary>60000</salary>
        <exp>5</exp>
        <sex>f</sex>
        <addresses>
            <address1>My Address1</address1>
            <address2>My Address2</address2>
        </addresses>
    </sampledata>
</sample>

 

Temmplate File :

<#ftl strip_whitespace = true>

<#assign charset="UTF-8">
<#assign title="Example">
<#assign content>
This is content
</#assign>
<!DOCTYPE html>
<html>
    <head>
        <title>${title}</title>
        <meta charset="${charset}">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        </head>
    <body>  
        <#foreach sample in samples.sample.sampledata>
            <div>
                id:${sample.id}
                name: ${sample.name}
                age:${sample.age}
                salary:${sample.salary}
                exp:${sample.exp}
                sex:${sample.sex}
                <#foreach address in sample.addresses>
                <div>
                    address1:${address.address1}
                    <#if "${address.address2}"!="">
                    address1:${address.address2}
                    </#if>
                </div>
                </#foreach>
            </div> 
        </#foreach>
        </body>
    </html>

No comments:

Post a Comment