0
# XML Utilities
1
2
Groovy XML provides comprehensive utility classes for XML serialization, pretty printing, escaping, and parser configuration.
3
4
## XmlUtil
5
6
Central utility class providing static methods for XML serialization, parser creation, and content escaping.
7
8
```java { .api }
9
public class XmlUtil {
10
// Serialization methods for various types
11
public static String serialize(Element element);
12
public static void serialize(Element element, OutputStream os) throws IOException;
13
public static void serialize(Element element, Writer w) throws IOException;
14
public static String serialize(Node node);
15
public static void serialize(Node node, OutputStream os) throws IOException;
16
public static void serialize(Node node, Writer w) throws IOException;
17
public static String serialize(GPathResult node);
18
public static void serialize(GPathResult node, OutputStream os) throws IOException;
19
public static void serialize(GPathResult node, Writer w) throws IOException;
20
public static String serialize(Writable writable);
21
public static void serialize(Writable writable, OutputStream os) throws IOException;
22
public static void serialize(Writable writable, Writer w) throws IOException;
23
public static String serialize(String xmlString);
24
public static void serialize(String xmlString, OutputStream os) throws IOException;
25
public static void serialize(String xmlString, Writer w) throws IOException;
26
27
// SAX Parser factory methods
28
public static SAXParser newSAXParser(String schemaLanguage, Source... schemas)
29
throws ParserConfigurationException, SAXException;
30
public static SAXParser newSAXParser(String schemaLanguage, boolean namespaceAware,
31
boolean validating, Source... schemas) throws ParserConfigurationException, SAXException;
32
public static SAXParser newSAXParser(String schemaLanguage, File schema)
33
throws ParserConfigurationException, SAXException;
34
public static SAXParser newSAXParser(String schemaLanguage, boolean namespaceAware,
35
boolean validating, File schema) throws ParserConfigurationException, SAXException;
36
public static SAXParser newSAXParser(String schemaLanguage, URL schema)
37
throws ParserConfigurationException, SAXException;
38
public static SAXParser newSAXParser(String schemaLanguage, boolean namespaceAware,
39
boolean validating, URL schema) throws ParserConfigurationException, SAXException;
40
41
// XML escaping utilities
42
public static String escapeXml(String orig);
43
public static String escapeControlCharacters(String orig);
44
}
45
```
46
47
### XmlUtil Usage Examples
48
49
```groovy
50
// Serialize different types of XML objects
51
def parser = new XmlParser()
52
def node = parser.parseText('<root><item>value</item></root>')
53
54
// Serialize Node to string
55
def xmlString = XmlUtil.serialize(node)
56
println xmlString // Formatted XML string
57
58
// Serialize to OutputStream
59
def baos = new ByteArrayOutputStream()
60
XmlUtil.serialize(node, baos)
61
println baos.toString()
62
63
// Serialize to Writer
64
def writer = new StringWriter()
65
XmlUtil.serialize(node, writer)
66
println writer.toString()
67
68
// Serialize GPathResult
69
def slurper = new XmlSlurper()
70
def gpath = slurper.parseText('<root><item>value</item></root>')
71
def serialized = XmlUtil.serialize(gpath)
72
73
// Serialize DOM Element
74
def domBuilder = DOMBuilder.newInstance()
75
def doc = domBuilder.root { item('value') }
76
def element = doc.documentElement
77
def domSerialized = XmlUtil.serialize(element)
78
79
// Serialize Writable (from StreamingMarkupBuilder)
80
def smb = new StreamingMarkupBuilder()
81
def writable = smb.bind { root { item('value') } }
82
def writableSerialized = XmlUtil.serialize(writable)
83
84
// Pretty-print existing XML string
85
def uglyXml = '<root><item>value</item><item2>value2</item2></root>'
86
def prettyXml = XmlUtil.serialize(uglyXml)
87
println prettyXml // Nicely formatted
88
```
89
90
### XML Escaping
91
92
```groovy
93
// Escape special XML characters
94
def rawText = 'This contains <special> & "characters" that need \'escaping\''
95
def escaped = XmlUtil.escapeXml(rawText)
96
println escaped // "This contains <special> & "characters" that need 'escaping'"
97
98
// Escape control characters
99
def controlText = "Line 1\u0001\nLine 2\u0002"
100
def escapedControl = XmlUtil.escapeControlCharacters(controlText)
101
println escapedControl
102
103
// Use in builders
104
def xml = new MarkupBuilder(writer)
105
xml.root {
106
content(XmlUtil.escapeXml(userInput))
107
// or let the builder handle escaping automatically
108
autoEscaped(userInput)
109
}
110
```
111
112
### SAX Parser Factory
113
114
```groovy
115
// Create SAX parser with schema validation
116
def xsdFile = new File('schema.xsd')
117
def parser = XmlUtil.newSAXParser(XMLConstants.W3C_XML_SCHEMA_NS_URI, xsdFile)
118
119
// Create with namespace awareness and validation
120
def validatingParser = XmlUtil.newSAXParser(
121
XMLConstants.W3C_XML_SCHEMA_NS_URI,
122
true, // namespace aware
123
true, // validating
124
xsdFile
125
)
126
127
// Create with multiple schemas
128
def schema1 = new StreamSource(new File('schema1.xsd'))
129
def schema2 = new StreamSource(new File('schema2.xsd'))
130
def multiSchemaParser = XmlUtil.newSAXParser(
131
XMLConstants.W3C_XML_SCHEMA_NS_URI,
132
schema1, schema2
133
)
134
135
// Use with XmlParser
136
def xmlParser = new XmlParser(validatingParser)
137
def validatedNode = xmlParser.parse(new File('document.xml'))
138
```
139
140
## XmlNodePrinter
141
142
Specialized pretty-printer for Node structures with extensive formatting options.
143
144
```java { .api }
145
public class XmlNodePrinter {
146
// Constructors
147
public XmlNodePrinter();
148
public XmlNodePrinter(PrintWriter out);
149
public XmlNodePrinter(PrintWriter out, String indent);
150
public XmlNodePrinter(PrintWriter out, String indent, String quote);
151
public XmlNodePrinter(IndentPrinter out);
152
public XmlNodePrinter(IndentPrinter out, String quote);
153
154
// Main printing method
155
public void print(Node node);
156
157
// Configuration methods
158
public boolean isNamespaceAware();
159
public void setNamespaceAware(boolean namespaceAware);
160
public boolean isPreserveWhitespace();
161
public void setPreserveWhitespace(boolean preserveWhitespace);
162
public String getQuote();
163
public void setQuote(String quote);
164
public boolean isExpandEmptyElements();
165
public void setExpandEmptyElements(boolean expandEmptyElements);
166
}
167
```
168
169
### XmlNodePrinter Usage
170
171
```groovy
172
def parser = new XmlParser()
173
def node = parser.parseText('''
174
<root xmlns:ns="http://example.com">
175
<item id="1">Value 1</item>
176
<item id="2"></item>
177
<ns:special>Namespaced content</ns:special>
178
</root>
179
''')
180
181
// Basic pretty printing
182
def writer = new StringWriter()
183
def printer = new XmlNodePrinter(new PrintWriter(writer))
184
printer.print(node)
185
println writer.toString()
186
187
// Customized formatting
188
def customWriter = new StringWriter()
189
def customPrinter = new XmlNodePrinter(
190
new PrintWriter(customWriter),
191
" ", // 4-space indent
192
"\"" // double quotes for attributes
193
)
194
195
// Configure additional options
196
customPrinter.setNamespaceAware(true)
197
customPrinter.setPreserveWhitespace(false)
198
customPrinter.setExpandEmptyElements(true) // <item></item> instead of <item/>
199
200
customPrinter.print(node)
201
println customWriter.toString()
202
203
// Using IndentPrinter for more control
204
def indentWriter = new StringWriter()
205
def indentPrinter = new IndentPrinter(indentWriter, " ")
206
def nodePrinter = new XmlNodePrinter(indentPrinter, "'") // single quotes
207
208
nodePrinter.print(node)
209
println indentWriter.toString()
210
```
211
212
## Extension Methods (XmlGroovyMethods)
213
214
Extension methods that add XML functionality to existing Java classes.
215
216
```java { .api }
217
public class XmlGroovyMethods {
218
// Extends NodeList to make it iterable
219
public static Iterator<Node> iterator(NodeList nodeList);
220
221
// Extends Element for convenient serialization
222
public static String serialize(Element element);
223
}
224
```
225
226
### Extension Methods Usage
227
228
```groovy
229
// Working with DOM NodeList
230
def domDoc = DOMBuilder.parse(new StringReader('<root><item/><item/></root>'))
231
def nodeList = domDoc.getElementsByTagName('item')
232
233
// NodeList is now iterable thanks to extension method
234
nodeList.each { element ->
235
println "Element: ${element.tagName}"
236
}
237
238
// Direct iteration
239
for (element in nodeList) {
240
println "Element: ${element.tagName}"
241
}
242
243
// DOM Element serialization
244
def rootElement = domDoc.documentElement
245
def serialized = rootElement.serialize() // Extension method
246
println serialized
247
```
248
249
## Factory Classes
250
251
### FactorySupport
252
253
Base class for XML factory implementations.
254
255
```java { .api }
256
public class FactorySupport {
257
// Configuration methods for SAX factories
258
protected void setDocumentBuilderFactory(DocumentBuilderFactory documentBuilderFactory);
259
protected void setSAXParserFactory(SAXParserFactory saxParserFactory);
260
protected void setTransformerFactory(TransformerFactory transformerFactory);
261
}
262
```
263
264
### XmlParserFactory
265
266
Factory for creating XmlParser instances (primarily for migration support).
267
268
```groovy { .api }
269
class XmlParserFactory {
270
static Object newParser(Object... args)
271
}
272
```
273
274
### XmlSlurperFactory
275
276
Factory for creating XmlSlurper instances.
277
278
```groovy { .api }
279
class XmlSlurperFactory {
280
static Object newSlurper(Object... args)
281
}
282
```
283
284
### Factory Usage
285
286
```groovy
287
// Using parser factory
288
def parser = XmlParserFactory.newParser(
289
true, // validating
290
true // namespace aware
291
)
292
293
// Using slurper factory
294
def slurper = XmlSlurperFactory.newSlurper(false, true)
295
296
// Custom factory configurations
297
def customFactory = new FactorySupport() {
298
// Override factory configuration
299
}
300
```
301
302
## Validation and Schema Support
303
304
```groovy
305
// Create validating parsers with schemas
306
def createValidatingParser = { schemaFile ->
307
def parser = XmlUtil.newSAXParser(
308
XMLConstants.W3C_XML_SCHEMA_NS_URI,
309
true, // namespace aware
310
true, // validating
311
schemaFile
312
)
313
return new XmlParser(parser)
314
}
315
316
// Validate against XSD
317
def xsdFile = new File('catalog.xsd')
318
def validatingParser = createValidatingParser(xsdFile)
319
320
try {
321
def validatedDoc = validatingParser.parse(new File('catalog.xml'))
322
println "Document is valid"
323
} catch (SAXException e) {
324
println "Validation error: ${e.message}"
325
}
326
327
// RelaxNG validation
328
def relaxNGSchema = new File('schema.rng')
329
def relaxNGParser = XmlUtil.newSAXParser(
330
XMLConstants.RELAXNG_NS_URI,
331
relaxNGSchema
332
)
333
```
334
335
## Performance Utilities
336
337
```groovy
338
// Efficient serialization for large documents
339
def serializeLargeDocument = { node, outputFile ->
340
new FileOutputStream(outputFile).withStream { fos ->
341
XmlUtil.serialize(node, fos)
342
}
343
}
344
345
// Memory-efficient pretty printing
346
def prettyPrintToFile = { node, outputFile ->
347
new FileWriter(outputFile).withWriter { writer ->
348
def printer = new XmlNodePrinter(new PrintWriter(writer))
349
printer.print(node)
350
}
351
}
352
353
// Streaming serialization
354
def streamingSerialize = { writable, outputStream ->
355
XmlUtil.serialize(writable, outputStream)
356
}
357
```
358
359
## Utility Best Practices
360
361
```groovy
362
// Always escape user input
363
def safeXmlContent = { userInput ->
364
return XmlUtil.escapeXml(userInput ?: "")
365
}
366
367
// Use appropriate serialization method
368
def serializeBasedOnType = { xmlObject ->
369
switch (xmlObject) {
370
case Node:
371
return XmlUtil.serialize(xmlObject as Node)
372
case GPathResult:
373
return XmlUtil.serialize(xmlObject as GPathResult)
374
case Element:
375
return XmlUtil.serialize(xmlObject as Element)
376
case Writable:
377
return XmlUtil.serialize(xmlObject as Writable)
378
default:
379
return XmlUtil.serialize(xmlObject.toString())
380
}
381
}
382
383
// Configure printers for consistent output
384
def createStandardPrinter = { writer ->
385
def printer = new XmlNodePrinter(new PrintWriter(writer), " ", "\"")
386
printer.setNamespaceAware(true)
387
printer.setPreserveWhitespace(false)
388
printer.setExpandEmptyElements(false)
389
return printer
390
}
391
```