Five minute Introduction

Five minute Introduction

examples are for v3 not v4

This short introduction to StringTemplate will hopefully help you answer the following:

  • What is StringTemplate?
  • What does StringTemplate do?
  • What can I do with StringTemplate?
  • How do I get started using StringTemplate?
  • Where do I learn more about StringTemplate?

What is StringTemplate?

StringTemplate (or ST) is a template engine library used for generating text from data structures. The first version was developed for the Java platform and has evolved over the years of it's use on the jGuru.com website. StringTemplate's distinguishing characteristic is that it strictly enforces model-view separation unlike other comparable template engines. It is particularly good at multi-targeted code generators, multiple site skins, and internationalization/localization.

Independent implementations of some versions of StringTemplate are available in C# and Python (discussions about Objective-C and C++ implementations of StringTemplate occur frequently on the mailing list). StringTemplate is currently used to generate the ANTLR website and the StringTemplate website. It is also the engine that powers the powerful, flexible, multi-language, retargetable code generator in the ANTLR v3 language tool generator.

What does StringTemplate do?

Structured text generation. StringTemplate supports the generation of structured text output such as web pages, source code, emails and newsletters from arbitary data structures without sacrificing model-view separation.

StringTemplate is non-intrusive and doesn't require your data structures to implement any specific contracts. It is designed to be embedded inside other applications and is distributed as a small library with no external dependencies except ANTLR (used for parsing the StringTemplate template language) and, the standard platform libraries (e.g. JDK 1.2 for the Java version).

Why should I use StringTemplate?

To ensure the separation of the specification of business logic and computation required to generate structured text from the specification of how that text is presented (i.e. it's formatting).

For web developers, this translates to ensuring that a web page's business and persistence logic is separated from the the page's presentation.

For developers involved in code generation, this translates to ensuring generation and persistence logic is separated from output code structure. This separation directly supports the development of retargetable code generators.

Other benefits of model-view separation:

  1. Encourages the development of templates that are reusable in similar applications
  2. Unentangled templates serves as clear documentation of the generated code structure
  3. The templates (and hence the output or view) can be changed independently. Using more than one set of such templates is the basic mechanism for retargetable code generation

How do I use StringTemplate?

1. Get StringTemplate

Download and install StringTemplate from the download page on the StringTemplate website

2. Learn basic StringTemplate syntax

Please note that:

  1. each example in the table below fits on a single line but, it may appear on more than a line in the table due to space restrictions and wrapping.
  2. StringTemplate supports the use of <...> and $...$ as delimiters (as shown in the examples)

Syntax

Description

Example

<attribute>

Replaced with value of attribute.ToString() (or empty string if missing).

$user$
<user>

<attribute.property>

Replaced with value of property of attribute (or empty string if missing).

$user.name$
<user.name>

<attribute.(expr)>

Indirect property lookup. Same as attribute.property except value of expr is the property name.

$user.(name_label)$
<user.(name_label)>

<multi-valued-attribute>

Concatenation of ToString() invoked on each element.

$users$
<users>

<multi-valued-attribute; separator=expr>

Concatenation of ToString() invoked on each element separated by expr.

$users; separator=", "$
<users; separator=", ">

<template(argument-list)>

Include (i.e. call) template. argument-list is a list of attribute assignments of the form arg-of-template=expr. expr is evaluated in the context of the surrounding template not of the invoked template.

$bold()$
<bold(item=title)>

<attribute:template(argument-list)>

Template application. The optional argument-list is evaluated before application. The default attribute it is set to the value of attribute. If attribute is multi-valued, it is set to each element in turn and template is invoked n times where n is the number of values in attribute.

$name:bold()$
<name:checkoutReceipt(items=skus, ship=shipOpt)>

<attribute:{argument-name_ | _anonymous-template}>

Apply an anonymous template to each element of attribute. Set the argument-name to the iterated value and also set it.

$users:{s|<li>$s$</li>}; separator="\n"$
<users:{s|<li>$s$</li>}; separator="\n">

<if(!attribute)>subtemplate<endif>

If attribute has no value or is a bool object that evaluates to false, include subtemplate. These conditionals may be nested.

$if(users)$ $users:{u|$u$}$ $endif$
<if(users)> <users:{u|<u>}> <endif>

\$ or \<

escaped delimiter prevents $ or < from starting an attribute expression and results in that single character.

\$
\<

<\ >, <\n>, <\t>, <\r>

special characters: space, newline, tab, carriage return.

$\n$
<\n>

<! comment !>, $! comment !$

Comments, ignored by StringTemplate.

$! this is a comment !$
<! this is a comment !>

3. Create and use a template in code

Where better to start than a StringTemplate version of the ubiquitous "Hello, World" example... (wink)

Starting with version 2.3, StringTemplate uses <..> as it's default delimiters. For completeness, we will use $..$ here to illustrate how specific delimiters are specified with StringTemplate.

Java

import org.antlr.stringtemplate.*;
import org.antlr.stringtemplate.language.*;

StringTemplate hello = new StringTemplate("Hello, $name$", DefaultTemplateLexer.class);
hello.setAttribute("name", "World");
System.out.println(hello.toString());

C#

using Antlr.StringTemplate;
using Antlr.StringTemplate.Language;

StringTemplate hello = new StringTemplate("Hello, $name$", typeof(DefaultTemplateLexer));
hello.SetAttribute("name", "World");
Console.Out.WriteLine(hello.ToString());

Python
v2.2

import stringtemplate

hello = stringtemplate.StringTemplate("Hello, $name$")
hello["name"] = "World"
print str(hello)

Python
v3.1

import stringtemplate3

hello = stringtemplate3.StringTemplate("Hello, $name$")
hello["name"] = "World"
print str(hello)

4. Create and use a template from a file

First, create the homepage.st template file as shown below and save it to a location on your system.

homepage.st
<html>
    <head>
       <title>$title$</title>
    </head>
    <body>
       <p>Hello again, $name$ !</p>
       <p>Greetings to your friends $rest(friends); separator=", "$</p>
   </body>
</html>

This tutorial is written with the assumption that the template was saved to C:\Tutorials\homepage.st. Please change the directory name in the code below to reflect the actual location of homepage.st on you system.

Next, create the code that loads and uses the template file. To do so, we will make use of the StringTemplateGroup class that manages external templates.

java

import org.antlr.stringtemplate.*;
import org.antlr.stringtemplate.language.*;

StringTemplateGroup group =  new StringTemplateGroup("myGroup", "C:\\Tutorials", DefaultTemplateLexer.class);
StringTemplate helloAgain = group.getInstanceOf("homepage");

helloAgain.setAttribute("title", "Welcome To StringTemplate");
helloAgain.setAttribute("name", "World");
helloAgain.setAttribute("friends", "Ter");
helloAgain.setAttribute("friends", "Kunle");
helloAgain.setAttribute("friends", "Micheal");
helloAgain.setAttribute("friends", "Marq");

System.out.println(helloAgain.toString());

C#

using System;
using Antlr.StringTemplate;
using Antlr.StringTemplate.Language;

StringTemplateGroup group =  new StringTemplateGroup("myGroup", @"C:\Tutorials", typeof(DefaultTemplateLexer));
StringTemplate helloAgain = group.GetInstanceOf("homepage");

helloAgain.SetAttribute("title", "Welcome To StringTemplate");
helloAgain.SetAttribute("name", "World");
helloAgain.SetAttribute("friends", "Terence");
helloAgain.SetAttribute("friends", "Kunle");
helloAgain.SetAttribute("friends", "Micheal");
helloAgain.SetAttribute("friends", "Marq");

Console.Out.WriteLine(helloAgain.ToString());

Python

import stringtemplate

group = stringtemplate.StringTemplateGroup("myGroup", "C:\\Tutorials")
helloAgain = group.getInstanceOf("homepage")

helloAgain["title"] = "Welcome To StringTemplate"
helloAgain["name"] = "World"
helloAgain["friends"] = "Terence"
helloAgain["friends"] = "Kunle"
helloAgain["friends"] = "Micheal"
helloAgain["friends"] = "Marq"

print str(helloAgain)

Python 3

import stringtemplate3

group = stringtemplate3.StringTemplateGroup("myGroup", "C:\\Tutorials")
helloAgain = group.getInstanceOf("homepage")

helloAgain["title"] = "Welcome To StringTemplate"
helloAgain["name"] = "World"
helloAgain["friends"] = "Terence"
helloAgain["friends"] = "Kunle"
helloAgain["friends"] = "Micheal"
helloAgain["friends"] = "Marq"

print(str(helloAgain))

What next?

Read the StringTemplate Documentation

Browse the list of questions frequently asked about StringTemplate

Your five minutes are up!

If this guide has been helpful to you, please consider contributing to this wiki when you are more familiar with StringTemplate.

Thanks