views:

183

answers:

2

Pretty sure there is an easy answer to this, but just can't find the right VTL syntax.

In my context I'm passing a Map which contains other Maps. I'd like to reference these inner maps by name and assign them within my template. The inner maps are constructed by different parts of the app, and then added to the context

by way of example

public static void main( String[] args )
    throws Exception
{

    VelocityEngine ve = new VelocityEngine();
    ve.init();
    Template t = ve.getTemplate( "test.vm" );
    VelocityContext context = new VelocityContext();

    Map<String,Map<String,String>> messageData = new HashMap<String, Map<String,String>>();


    Map<String,String> data_map = new HashMap<String,String>();
    data_map.put("data_1","1234");
    data_map.put("a_date", "31-Dec-2009");

    messageData.put("inner_map", data_map);

    context.put("msgData", messageData);
    StringWriter writer = new StringWriter();

    t.merge( context, writer );
    System.out.println( writer.toString() );
}

Template - test.vm

#set ($in_map =  $msgData.get($inner_map) )

data:

    $in_map.data_1
    $in_map.a_date  
+1  A: 

Try

${in_map.get("data_1")}

or

${in_map.get("a_date")}
Drew
A: 

The answer given didn't work for me but did get me thinking about the problem in a different way. I Resolved this by creating a method which can lookup subsections of data based on a string and returns a list of maps.

#set( $data = $confirmData.getCollection("MSG_DATA").get(0) )

This even works if your underlying data is an XML document, as you can pass in an xPath and have the method return a map of the tagName tagValues. This provides a lot of flexibility.

#set( $data = $confirmData.getCollection("//Message/header[sendFrom='xxx']").get(0) )
Wiretap