0
# XML Generation and Output
1
2
Utilities for programmatically generating well-formed XML with proper indentation and encoding. The XmlAppendable class provides a fluent API for creating XML documents with automatic formatting and proper escaping.
3
4
## Capabilities
5
6
### XmlAppendable Class
7
8
Helper class for generating well-formed XML with proper indentation and character escaping.
9
10
```java { .api }
11
/**
12
* Helper for generating well-formed XML with proper indentation
13
*/
14
class XmlAppendable {
15
/**
16
* Create XML appendable writing to output stream
17
* @param out output stream for XML content
18
*/
19
XmlAppendable(OutputStream out);
20
}
21
```
22
23
### Tag Creation
24
25
Create XML elements with opening and closing tags.
26
27
```java { .api }
28
/**
29
* Open XML tag
30
* @param tag tag name
31
* @return this XmlAppendable for chaining
32
*/
33
XmlAppendable openTag(String tag);
34
35
/**
36
* Open tag with attributes
37
* @param tag tag name
38
* @param attributes map of attribute name-value pairs
39
* @return this XmlAppendable for chaining
40
*/
41
XmlAppendable openTag(String tag, Map<String, String> attributes);
42
43
/**
44
* Close current tag
45
* @return this XmlAppendable for chaining
46
*/
47
XmlAppendable closeTag();
48
```
49
50
### Self-Closing Tags
51
52
Create self-closing XML elements.
53
54
```java { .api }
55
/**
56
* Create self-closing tag
57
* @param tag tag name
58
* @return this XmlAppendable for chaining
59
*/
60
XmlAppendable tag(String tag);
61
62
/**
63
* Create self-closing tag with attributes
64
* @param tag tag name
65
* @param attributes map of attribute name-value pairs
66
* @return this XmlAppendable for chaining
67
*/
68
XmlAppendable tag(String tag, Map<String, String> attributes);
69
```
70
71
### Tags with Content
72
73
Create complete XML elements with text content.
74
75
```java { .api }
76
/**
77
* Create tag with text content
78
* @param tag tag name
79
* @param content text content (will be escaped)
80
* @return this XmlAppendable for chaining
81
*/
82
XmlAppendable tag(String tag, String content);
83
84
/**
85
* Create tag with attributes and content
86
* @param tag tag name
87
* @param attributes map of attribute name-value pairs
88
* @param content text content (will be escaped)
89
* @return this XmlAppendable for chaining
90
*/
91
XmlAppendable tag(String tag, Map<String, String> attributes, String content);
92
```
93
94
### Content Methods
95
96
Add various types of content to XML documents.
97
98
```java { .api }
99
/**
100
* Add sanitized text content (XML characters escaped)
101
* @param s text content to add
102
* @return this XmlAppendable for chaining
103
*/
104
XmlAppendable content(String s);
105
106
/**
107
* Add CDATA section
108
* @param s content for CDATA section
109
* @return this XmlAppendable for chaining
110
*/
111
XmlAppendable cdata(String s);
112
113
/**
114
* Create tag with CDATA content
115
* @param tag tag name
116
* @param data content for CDATA section
117
* @return this XmlAppendable for chaining
118
*/
119
XmlAppendable tagCDATA(String tag, String data);
120
121
/**
122
* Add literal XML content (not escaped)
123
* @param xml XML content to add literally
124
*/
125
void literal(String xml);
126
```
127
128
## Usage Examples
129
130
### Basic XML Generation
131
132
```java
133
import org.eclipse.jetty.xml.XmlAppendable;
134
import java.io.FileOutputStream;
135
import java.io.IOException;
136
import java.util.Map;
137
138
// Create XML generator
139
try (FileOutputStream out = new FileOutputStream("output.xml")) {
140
XmlAppendable xml = new XmlAppendable(out);
141
142
// Generate simple XML
143
xml.openTag("root")
144
.tag("element", "content")
145
.closeTag();
146
}
147
```
148
149
### XML with Attributes
150
151
```java
152
import java.util.HashMap;
153
154
XmlAppendable xml = new XmlAppendable(outputStream);
155
156
// Create attributes map
157
Map<String, String> attributes = new HashMap<>();
158
attributes.put("class", "com.example.Server");
159
attributes.put("id", "mainServer");
160
161
// Generate XML with attributes
162
xml.openTag("Configure", attributes)
163
.tag("Set", Map.of("name", "port"), "8080")
164
.tag("Set", Map.of("name", "host"), "localhost")
165
.closeTag();
166
```
167
168
### Complex Configuration Generation
169
170
```java
171
XmlAppendable xml = new XmlAppendable(outputStream);
172
173
// Generate Jetty-style configuration
174
xml.openTag("Configure", Map.of("class", "org.eclipse.jetty.server.Server"))
175
176
// Set server port
177
.openTag("Set", Map.of("name", "port"))
178
.openTag("Property", Map.of("name", "jetty.port", "default", "8080"))
179
.closeTag()
180
.closeTag()
181
182
// Add connector
183
.openTag("Call", Map.of("name", "addConnector"))
184
.openTag("Arg")
185
.openTag("New", Map.of("class", "org.eclipse.jetty.server.ServerConnector"))
186
.openTag("Arg")
187
.openTag("Ref", Map.of("refid", "Server"))
188
.closeTag()
189
.closeTag()
190
.closeTag()
191
.closeTag()
192
.closeTag()
193
194
.closeTag(); // Close Configure
195
```
196
197
### Self-Closing Tags
198
199
```java
200
XmlAppendable xml = new XmlAppendable(outputStream);
201
202
// Generate self-closing elements
203
xml.openTag("configuration")
204
.tag("property", Map.of("name", "enabled", "value", "true"))
205
.tag("include", Map.of("file", "additional.xml"))
206
.closeTag();
207
```
208
209
### CDATA Content
210
211
```java
212
XmlAppendable xml = new XmlAppendable(outputStream);
213
214
// Add CDATA sections for complex content
215
xml.openTag("script")
216
.cdata("function test() { return x < y && a > b; }")
217
.closeTag();
218
219
// Or use convenience method
220
xml.tagCDATA("description", "This contains <special> & characters");
221
```
222
223
### Mixed Content Types
224
225
```java
226
XmlAppendable xml = new XmlAppendable(outputStream);
227
228
xml.openTag("document")
229
.content("This is plain text content with <escaped> characters")
230
.openTag("code")
231
.cdata("unescaped <code> & content")
232
.closeTag()
233
.literal("<!-- This is literal XML -->")
234
.closeTag();
235
```
236
237
### Fluent API Chaining
238
239
```java
240
XmlAppendable xml = new XmlAppendable(outputStream);
241
242
// Chain multiple operations fluently
243
xml.openTag("server")
244
.tag("name", "Production Server")
245
.tag("port", "8080")
246
.tag("ssl-enabled", "true")
247
.openTag("connectors")
248
.tag("connector", Map.of("type", "http", "port", "8080"))
249
.tag("connector", Map.of("type", "https", "port", "8443"))
250
.closeTag()
251
.openTag("handlers")
252
.tag("handler", Map.of("class", "WebAppHandler", "contextPath", "/"))
253
.closeTag()
254
.closeTag();
255
```
256
257
### Generate Configuration from Data
258
259
```java
260
import java.util.List;
261
262
public void generateServerConfig(List<ServerConfig> configs, OutputStream out) {
263
XmlAppendable xml = new XmlAppendable(out);
264
265
xml.openTag("Configure", Map.of("class", "org.eclipse.jetty.server.Server"));
266
267
for (ServerConfig config : configs) {
268
Map<String, String> setAttrs = Map.of("name", config.getPropertyName());
269
xml.tag("Set", setAttrs, config.getPropertyValue());
270
}
271
272
xml.closeTag();
273
}
274
```
275
276
### Error Handling
277
278
```java
279
try (FileOutputStream out = new FileOutputStream("config.xml")) {
280
XmlAppendable xml = new XmlAppendable(out);
281
282
xml.openTag("configuration")
283
.tag("setting", "value")
284
.closeTag();
285
286
} catch (IOException e) {
287
System.err.println("Failed to write XML: " + e.getMessage());
288
}
289
```
290
291
## XML Output Features
292
293
### Automatic Indentation
294
295
The XmlAppendable class automatically handles proper indentation:
296
297
```xml
298
<Configure class="org.eclipse.jetty.server.Server">
299
<Set name="port">8080</Set>
300
<Call name="addConnector">
301
<Arg>
302
<New class="org.eclipse.jetty.server.ServerConnector">
303
<Arg><Ref refid="Server"/></Arg>
304
</New>
305
</Arg>
306
</Call>
307
</Configure>
308
```
309
310
### Character Escaping
311
312
Text content is automatically escaped for XML safety:
313
314
- `<` becomes `<`
315
- `>` becomes `>`
316
- `&` becomes `&`
317
- `"` becomes `"` in attributes
318
- `'` becomes `'` in attributes
319
320
### CDATA Support
321
322
CDATA sections preserve content without escaping:
323
324
```xml
325
<script><![CDATA[
326
function test() {
327
return x < y && a > b;
328
}
329
]]></script>
330
```
331
332
## Best Practices
333
334
1. **Always close tags**: Use try-with-resources or ensure proper tag closure
335
2. **Use CDATA for complex content**: When content contains XML metacharacters
336
3. **Validate attribute values**: Ensure attribute values are properly formatted
337
4. **Handle I/O exceptions**: Wrap file operations in proper exception handling
338
5. **Use fluent chaining**: Take advantage of method chaining for cleaner code