Groovy templating engines providing JSP-style scripting, GString expressions, markup builders, and streaming template capabilities for generating dynamic content from templates with variable substitution and control flow
—
The XmlTemplateEngine is designed for scenarios where both the template source and expected output are XML. It provides special GSP (Groovy Server Pages) tags for embedding code and expressions while maintaining well-formed XML structure.
class XmlTemplateEngine extends TemplateEngine {
XmlTemplateEngine() throws SAXException, ParserConfigurationException;
XmlTemplateEngine(String indentation, boolean validating) throws SAXException, ParserConfigurationException;
XmlTemplateEngine(XmlParser xmlParser, ClassLoader parentLoader);
XmlTemplateEngine(XmlParser xmlParser, GroovyShell groovyShell);
Template createTemplate(Reader reader) throws CompilationFailedException, ClassNotFoundException, IOException;
void setIndentation(String indentation);
String getIndentation();
void setConfigurePrinter(Closure configurePrinter);
// Constants
static final String DEFAULT_INDENTATION = " ";
}<gsp:scriptlet>...</gsp:scriptlet> - Execute Groovy code fragments<gsp:expression>...</gsp:expression> - Output expression results${...} and $variable - Variable interpolation within text content<, >, ", ') are automatically escapedgsp: tags are removed from outputimport groovy.text.XmlTemplateEngine;
import groovy.text.Template;
import java.util.HashMap;
import java.util.Map;
XmlTemplateEngine engine = new XmlTemplateEngine();
String templateText = """
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns:gsp='http://groovy.codehaus.org/2005/gsp' xmlns:foo='baz' type='letter'>
<gsp:scriptlet>def greeting = "${salutation}est"</gsp:scriptlet>
<gsp:expression>greeting</gsp:expression>
<foo:to>$firstname "$nickname" $lastname</foo:to>
How are you today?
</document>
""";
Template template = engine.createTemplate(templateText);
Map<String, Object> binding = new HashMap<>();
binding.put("firstname", "Jochen");
binding.put("lastname", "Theodorou");
binding.put("nickname", "blackdrag");
binding.put("salutation", "Dear");
String result = template.make(binding).toString();Output:
<document type='letter'>
Dearest
<foo:to xmlns:foo='baz'>
Jochen "blackdrag" Theodorou
</foo:to>
How are you today?
</document>// Custom indentation (4 spaces instead of default 2)
XmlTemplateEngine engine = new XmlTemplateEngine(" ", false);
// Or set indentation after creation
engine.setIndentation("\t"); // Use tabs// Enable XML validation during parsing
XmlTemplateEngine engine = new XmlTemplateEngine(" ", true);import groovy.xml.XmlParser;
XmlParser customParser = new XmlParser();
customParser.setTrimWhitespace(false); // Preserve whitespace
ClassLoader customLoader = MyClass.class.getClassLoader();
XmlTemplateEngine engine = new XmlTemplateEngine(customParser, customLoader);XmlTemplateEngine engine = new XmlTemplateEngine();
// Configure the XML printer
engine.setConfigurePrinter(new Closure<Void>(this) {
public void doCall(Object printer) {
// printer is a GspPrinter instance
((groovy.text.XmlTemplateEngine.GspPrinter) printer).setPreserveWhitespace(true);
}
});String templateText = """
<?xml version="1.0" encoding="UTF-8"?>
<report xmlns:gsp='http://groovy.codehaus.org/2005/gsp'>
<header>
<title>$reportTitle</title>
<date><gsp:expression>new Date().format('yyyy-MM-dd')</gsp:expression></date>
</header>
<body>
<gsp:scriptlet>
def totalAmount = items.sum { it.price * it.quantity }
</gsp:scriptlet>
<items>
<gsp:scriptlet>
items.each { item ->
out.println("<item>")
out.println(" <name>${item.name}</name>")
out.println(" <price>${item.price}</price>")
out.println(" <quantity>${item.quantity}</quantity>")
out.println("</item>")
}
</gsp:scriptlet>
</items>
<summary>
<total>$totalAmount</total>
<gsp:scriptlet>
if (totalAmount > 1000) {
out.println("<discount>10%</discount>")
}
</gsp:scriptlet>
</summary>
</body>
</report>
""";
Map<String, Object> binding = new HashMap<>();
binding.put("reportTitle", "Sales Report");
binding.put("items", Arrays.asList(
Map.of("name", "Widget A", "price", 25.50, "quantity", 10),
Map.of("name", "Widget B", "price", 15.75, "quantity", 5)
));import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
try {
XmlTemplateEngine engine = new XmlTemplateEngine();
Template template = engine.createTemplate(xmlTemplateSource);
String result = template.make(binding).toString();
} catch (SAXException e) {
// XML parsing error
System.err.println("XML parsing failed: " + e.getMessage());
} catch (ParserConfigurationException e) {
// XML parser configuration error
System.err.println("XML parser configuration error: " + e.getMessage());
} catch (RuntimeException e) {
// Unsupported GSP tag or other runtime error
if (e.getMessage().contains("Unsupported 'gsp:' tag")) {
System.err.println("Invalid GSP tag: " + e.getMessage());
} else {
throw e;
}
}The XmlTemplateEngine can be used with TemplateServlet for web applications:
<!-- web.xml -->
<servlet>
<servlet-name>XmlTemplate</servlet-name>
<servlet-class>groovy.servlet.TemplateServlet</servlet-class>
<init-param>
<param-name>template.engine</param-name>
<param-value>groovy.text.XmlTemplateEngine</param-value>
</init-param>
</servlet>xmlns:gsp='http://groovy.codehaus.org/2005/gsp'The engine automatically escapes special XML characters in text content, but not within GString expressions. If you need to output literal XML characters within expressions, handle escaping manually:
String templateText = """
<message>
<content>User said: ${userInput}</content> <!-- Automatically escaped -->
<raw><gsp:expression>groovy.xml.XmlUtil.escapeXml(rawContent)</gsp:expression></raw> <!-- Manual escaping -->
</message>
""";Install with Tessl CLI
npx tessl i tessl/maven-org-codehaus-groovy--groovy-templates