0
# XML Templates
1
2
The XmlTemplateEngine provides specialized template processing for XML documents with `<gsp:scriptlet>` and `<gsp:expression>` support. It includes automatic XML escaping, proper indentation, and namespace handling for generating well-formed XML output.
3
4
## Capabilities
5
6
### XML Template Engine Class
7
8
Creates XML templates with automatic escaping, indentation, and GSP tag support.
9
10
```java { .api }
11
/**
12
* Template engine for XML templates with gsp:scriptlet and gsp:expression support.
13
* Provides automatic XML escaping, indentation, and namespace handling.
14
*/
15
public class XmlTemplateEngine extends TemplateEngine {
16
public static final String DEFAULT_INDENTATION = " ";
17
18
/**
19
* Creates a new XmlTemplateEngine with default settings
20
* @throws SAXException if XML parser configuration fails
21
* @throws ParserConfigurationException if XML parser cannot be configured
22
*/
23
public XmlTemplateEngine() throws SAXException, ParserConfigurationException;
24
25
/**
26
* Creates a new XmlTemplateEngine with custom indentation and validation
27
* @param indentation string used for indenting XML output
28
* @param validating true to enable XML validation during parsing
29
* @throws SAXException if XML parser configuration fails
30
* @throws ParserConfigurationException if XML parser cannot be configured
31
*/
32
public XmlTemplateEngine(String indentation, boolean validating) throws SAXException, ParserConfigurationException;
33
34
/**
35
* Creates a new XmlTemplateEngine with custom XML parser and class loader
36
* @param xmlParser XmlParser instance for parsing templates
37
* @param parentLoader ClassLoader for template compilation
38
*/
39
public XmlTemplateEngine(XmlParser xmlParser, ClassLoader parentLoader);
40
41
/**
42
* Creates a new XmlTemplateEngine with custom XML parser and Groovy shell
43
* @param xmlParser XmlParser instance for parsing templates
44
* @param groovyShell GroovyShell for script execution
45
*/
46
public XmlTemplateEngine(XmlParser xmlParser, GroovyShell groovyShell);
47
48
/**
49
* Get the current indentation string
50
* @return indentation string used for XML formatting
51
*/
52
public String getIndentation();
53
54
/**
55
* Set the indentation string for XML output
56
* @param indentation string to use for indenting (null defaults to DEFAULT_INDENTATION)
57
*/
58
public void setIndentation(String indentation);
59
60
/**
61
* Set a closure to configure the XML printer
62
* @param configurePrinter closure that receives the printer as parameter
63
*/
64
public void setConfigurePrinter(Closure configurePrinter);
65
}
66
```
67
68
**Usage Examples:**
69
70
```java
71
import groovy.text.XmlTemplateEngine;
72
import groovy.text.Template;
73
import groovy.xml.XmlParser;
74
import java.util.Map;
75
import java.util.HashMap;
76
77
// Create XML template engine with default settings
78
XmlTemplateEngine engine = new XmlTemplateEngine();
79
80
// XML template with GSP tags and variable substitution
81
String xmlTemplate = """
82
<?xml version="1.0" encoding="UTF-8"?>
83
<document xmlns:gsp='http://groovy.codehaus.org/2005/gsp' xmlns:foo='baz' type='letter'>
84
<gsp:scriptlet>def greeting = "${salutation}est"</gsp:scriptlet>
85
<gsp:expression>greeting</gsp:expression>
86
<foo:to>$firstname "$nickname" $lastname</foo:to>
87
<message>How are you today?</message>
88
</document>
89
""";
90
91
Template template = engine.createTemplate(xmlTemplate);
92
93
Map<String, Object> binding = new HashMap<>();
94
binding.put("firstname", "Jochen");
95
binding.put("lastname", "Theodorou");
96
binding.put("nickname", "blackdrag");
97
binding.put("salutation", "Dear");
98
99
String result = template.make(binding).toString();
100
// Output will be properly indented XML with gsp namespace removed
101
```
102
103
### GSP Tag Support
104
105
XmlTemplateEngine supports special GSP (Groovy Server Pages) tags for embedding logic in XML:
106
107
#### GSP Scriptlet Tag
108
Use `<gsp:scriptlet>` for executing Groovy code:
109
110
```xml
111
<document xmlns:gsp='http://groovy.codehaus.org/2005/gsp'>
112
<gsp:scriptlet>
113
def total = 0
114
items.each { item ->
115
total += item.price
116
}
117
</gsp:scriptlet>
118
<total>${total}</total>
119
</document>
120
```
121
122
#### GSP Expression Tag
123
Use `<gsp:expression>` for outputting expression results:
124
125
```xml
126
<document xmlns:gsp='http://groovy.codehaus.org/2005/gsp'>
127
<timestamp>
128
<gsp:expression>new Date().format('yyyy-MM-dd HH:mm:ss')</gsp:expression>
129
</timestamp>
130
<userCount>
131
<gsp:expression>users.size()</gsp:expression>
132
</userCount>
133
</document>
134
```
135
136
### Variable Substitution
137
138
XmlTemplateEngine supports GString-style variable substitution with automatic XML escaping:
139
140
```java
141
String template = """
142
<user>
143
<name>$user.name</name>
144
<email>${user.email}</email>
145
<bio>$user.bio</bio> <!-- Automatically XML-escaped -->
146
</user>
147
""";
148
149
Map<String, Object> binding = new HashMap<>();
150
Map<String, String> user = new HashMap<>();
151
user.put("name", "John Doe");
152
user.put("email", "john@example.com");
153
user.put("bio", "Software developer with <10 years experience & \"passion\" for code");
154
binding.put("user", user);
155
156
// Output will have proper XML escaping:
157
// <bio>Software developer with <10 years experience & "passion" for code</bio>
158
```
159
160
### XML Features
161
162
#### Automatic XML Escaping
163
Special XML characters are automatically escaped:
164
165
```java
166
// Input template
167
String template = """
168
<message>
169
$content
170
</message>
171
""";
172
173
Map<String, Object> binding = new HashMap<>();
174
binding.put("content", "Price: $5 < $10 & \"Special\" offer");
175
176
// Output will be properly escaped:
177
// <message>
178
// Price: $5 < $10 & "Special" offer
179
// </message>
180
```
181
182
#### Automatic Indentation
183
XML output is automatically indented for readability:
184
185
```java
186
XmlTemplateEngine engine = new XmlTemplateEngine();
187
188
// Custom indentation
189
XmlTemplateEngine customEngine = new XmlTemplateEngine(" ", false); // 4 spaces
190
191
// Configure indentation programmatically
192
engine.setIndentation("\t"); // Use tabs
193
```
194
195
#### Namespace Handling
196
GSP namespace is removed from output, other namespaces are preserved:
197
198
```xml
199
<!-- Input template -->
200
<root xmlns:gsp='http://groovy.codehaus.org/2005/gsp' xmlns:custom='http://example.com'>
201
<gsp:scriptlet>def value = "test"</gsp:scriptlet>
202
<custom:element>$value</custom:element>
203
</root>
204
205
<!-- Output (gsp namespace removed, custom namespace preserved) -->
206
<root>
207
<custom:element xmlns:custom='http://example.com'>test</custom:element>
208
</root>
209
```
210
211
### Configuration Options
212
213
#### Custom Indentation
214
Configure indentation string for XML output:
215
216
```java
217
// Use tabs for indentation
218
XmlTemplateEngine engine = new XmlTemplateEngine();
219
engine.setIndentation("\t");
220
221
// Use 4 spaces
222
engine.setIndentation(" ");
223
224
// No indentation (compact output)
225
engine.setIndentation("");
226
```
227
228
#### Printer Configuration
229
Use a closure to configure the XML printer:
230
231
```java
232
XmlTemplateEngine engine = new XmlTemplateEngine();
233
engine.setConfigurePrinter(new Closure(null) {
234
public void call(Object printer) {
235
// Configure printer properties
236
// printer.preserveWhitespace = true;
237
}
238
});
239
```
240
241
#### Validation
242
Enable XML validation during template parsing:
243
244
```java
245
// Enable validation
246
XmlTemplateEngine validatingEngine = new XmlTemplateEngine(" ", true);
247
```
248
249
### Advanced Usage
250
251
#### Custom XML Parser
252
Use a custom XML parser with specific configuration:
253
254
```java
255
import groovy.xml.XmlParser;
256
257
XmlParser customParser = new XmlParser();
258
customParser.setTrimWhitespace(false);
259
customParser.setNamespaceAware(true);
260
261
XmlTemplateEngine engine = new XmlTemplateEngine(customParser, getClass().getClassLoader());
262
```
263
264
#### Complex XML Generation
265
Generate complex XML structures with conditional logic:
266
267
```java
268
String template = """
269
<?xml version="1.0" encoding="UTF-8"?>
270
<catalog xmlns:gsp='http://groovy.codehaus.org/2005/gsp'>
271
<gsp:scriptlet>
272
def categories = products.groupBy { it.category }
273
</gsp:scriptlet>
274
275
<gsp:expression>
276
categories.each { category, items ->
277
out << "<category name='${category}'>"
278
items.each { product ->
279
out << "<product id='${product.id}' price='${product.price}'>${product.name}</product>"
280
}
281
out << "</category>"
282
}
283
</gsp:expression>
284
285
<summary>
286
<totalProducts><gsp:expression>products.size()</gsp:expression></totalProducts>
287
<totalCategories><gsp:expression>categories.size()</gsp:expression></totalCategories>
288
</summary>
289
</catalog>
290
""";
291
```
292
293
### Web Integration
294
295
XmlTemplateEngine can be used with servlet containers for generating XML responses:
296
297
```xml
298
<servlet>
299
<servlet-name>XmlTemplate</servlet-name>
300
<servlet-class>groovy.servlet.TemplateServlet</servlet-class>
301
<init-param>
302
<param-name>template.engine</param-name>
303
<param-value>groovy.text.XmlTemplateEngine</param-value>
304
</init-param>
305
</servlet>
306
```
307
308
### Error Handling
309
310
XmlTemplateEngine provides detailed error handling for XML-specific issues:
311
312
```java
313
try {
314
XmlTemplateEngine engine = new XmlTemplateEngine();
315
Template template = engine.createTemplate(xmlTemplate);
316
String result = template.make(binding).toString();
317
} catch (SAXException e) {
318
// XML parsing error in template source
319
System.err.println("XML parsing error: " + e.getMessage());
320
} catch (ParserConfigurationException e) {
321
// XML parser configuration issue
322
System.err.println("Parser configuration error: " + e.getMessage());
323
} catch (RuntimeException e) {
324
if (e.getMessage().contains("Parsing XML source failed")) {
325
// XML structure error
326
System.err.println("Invalid XML structure: " + e.getMessage());
327
} else {
328
throw e;
329
}
330
} catch (IOException e) {
331
// I/O error reading template
332
System.err.println("I/O error: " + e.getMessage());
333
}
334
```
335
336
### Best Practices
337
338
1. **Namespace Declaration**: Always declare the GSP namespace in your XML templates
339
2. **Escaping**: Let the engine handle XML escaping automatically - don't manually escape
340
3. **Indentation**: Use consistent indentation settings across your application
341
4. **Validation**: Enable validation during development to catch XML structure issues
342
5. **Comments**: XML comments and processing instructions are removed from output
343
6. **Performance**: Consider caching compiled templates for frequently used XML structures