0
# XML Processing
1
2
Comprehensive XML parsing, building, and manipulation with GPath expressions, builder patterns, and support for various XML processing approaches.
3
4
## Capabilities
5
6
### XML Parsing with XmlSlurper
7
8
Parse XML into GPath expressions for easy navigation and manipulation.
9
10
```groovy { .api }
11
/**
12
* Parser for XML into GPath expressions
13
*/
14
class XmlSlurper {
15
/** Create XmlSlurper with default configuration */
16
XmlSlurper()
17
18
/** Create XmlSlurper with validation enabled/disabled */
19
XmlSlurper(boolean validating)
20
21
/** Create XmlSlurper with custom XMLReader */
22
XmlSlurper(XMLReader reader)
23
24
/** Parse XML from string */
25
Object parseText(String text)
26
27
/** Parse XML from File */
28
Object parse(File file)
29
30
/** Parse XML from Reader */
31
Object parse(Reader reader)
32
33
/** Parse XML from InputStream */
34
Object parse(InputStream input)
35
36
/** Set feature on underlying XMLReader */
37
void setFeature(String feature, boolean value)
38
39
/** Set property on underlying XMLReader */
40
void setProperty(String property, Object value)
41
}
42
```
43
44
**Usage Examples:**
45
46
```groovy
47
import groovy.util.XmlSlurper
48
49
def xml = '''
50
<books>
51
<book id="1" category="fiction">
52
<title>The Great Gatsby</title>
53
<author>F. Scott Fitzgerald</author>
54
<price currency="USD">12.99</price>
55
<tags>
56
<tag>classic</tag>
57
<tag>american</tag>
58
</tags>
59
</book>
60
<book id="2" category="science">
61
<title>Brief History of Time</title>
62
<author>Stephen Hawking</author>
63
<price currency="USD">15.99</price>
64
<tags>
65
<tag>physics</tag>
66
<tag>cosmology</tag>
67
</tags>
68
</book>
69
</books>
70
'''
71
72
def books = new XmlSlurper().parseText(xml)
73
74
// Access elements and attributes
75
println books.book[0].title.text() // "The Great Gatsby"
76
println books.book[0].@id // "1"
77
println books.book[0].@category // "fiction"
78
println books.book[0].price.@currency // "USD"
79
80
// Iterate over elements
81
books.book.each { book ->
82
println "${book.title} by ${book.author} - \$${book.price}"
83
}
84
85
// Find specific elements
86
def fictionBooks = books.book.findAll { it.@category == 'fiction' }
87
def physicsBooks = books.book.findAll { book ->
88
book.tags.tag.any { it.text() == 'physics' }
89
}
90
91
// Modify XML content (returns new structure)
92
def updatedBooks = books.replaceNode {
93
books {
94
books.book.each { book ->
95
book {
96
title(book.title.text())
97
author(book.author.text())
98
price(book.price.text().toDouble() * 0.9, currency: book.price.@currency)
99
discounted('true')
100
}
101
}
102
}
103
}
104
```
105
106
### XML Parsing with XmlParser
107
108
Parse XML into Node objects for tree-based manipulation.
109
110
```groovy { .api }
111
/**
112
* Parser for XML into Node objects
113
*/
114
class XmlParser {
115
/** Create XmlParser with default configuration */
116
XmlParser()
117
118
/** Create XmlParser with validation enabled/disabled */
119
XmlParser(boolean validating)
120
121
/** Create XmlParser with custom XMLReader */
122
XmlParser(XMLReader reader)
123
124
/** Parse XML from string and return Node */
125
Node parseText(String text)
126
127
/** Parse XML from File and return Node */
128
Node parse(File file)
129
130
/** Parse XML from Reader and return Node */
131
Node parse(Reader reader)
132
133
/** Parse XML from InputStream and return Node */
134
Node parse(InputStream input)
135
136
/** Set feature on underlying XMLReader */
137
void setFeature(String feature, boolean value)
138
139
/** Set property on underlying XMLReader */
140
void setProperty(String property, Object value)
141
}
142
```
143
144
**Usage Examples:**
145
146
```groovy
147
import groovy.util.XmlParser
148
149
def parser = new XmlParser()
150
def root = parser.parseText(xml)
151
152
// Navigate using Node methods
153
println root.name() // "books"
154
println root.book[0].title.text() // "The Great Gatsby"
155
println root.book[0].attribute('id') // "1"
156
157
// Modify nodes in place
158
root.book[0].appendNode('isbn', '978-0-7432-7356-5')
159
root.book[0].price.setValue('10.99')
160
161
// Add new book
162
root.appendNode('book', [id: '3', category: 'mystery']) {
163
title('The Murder of Roger Ackroyd')
164
author('Agatha Christie')
165
price('13.99', [currency: 'USD'])
166
}
167
168
// Remove nodes
169
def nodeToRemove = root.book.find { it.@id == '2' }
170
if (nodeToRemove) {
171
root.remove(nodeToRemove)
172
}
173
```
174
175
### XML Building with MarkupBuilder
176
177
Create XML/HTML markup using a fluent builder API.
178
179
```groovy { .api }
180
/**
181
* Builder for creating XML/HTML markup
182
*/
183
class MarkupBuilder extends BuilderSupport {
184
/** Create MarkupBuilder writing to Writer */
185
MarkupBuilder(Writer writer)
186
187
/** Create MarkupBuilder writing to PrintWriter */
188
MarkupBuilder(PrintWriter writer)
189
190
/** Create MarkupBuilder with indentation */
191
MarkupBuilder(Writer writer, String indent)
192
193
/** Set XML declaration */
194
void setXmlDeclaration(boolean xmlDeclaration)
195
196
/** Set character encoding */
197
void setEncoding(String encoding)
198
199
/** Set whether to omit null attributes */
200
void setOmitNullAttributes(boolean omitNullAttributes)
201
202
/** Set whether to omit empty attributes */
203
void setOmitEmptyAttributes(boolean omitEmptyAttributes)
204
205
/** Set whether to expand empty elements */
206
void setExpandEmptyElements(boolean expandEmptyElements)
207
}
208
```
209
210
**Usage Examples:**
211
212
```groovy
213
import groovy.xml.MarkupBuilder
214
215
// Build XML to string
216
def writer = new StringWriter()
217
def xml = new MarkupBuilder(writer)
218
219
xml.books {
220
book(id: '1', category: 'fiction') {
221
title('The Great Gatsby')
222
author('F. Scott Fitzgerald')
223
price('12.99', currency: 'USD')
224
tags {
225
tag('classic')
226
tag('american')
227
}
228
}
229
book(id: '2', category: 'science') {
230
title('Brief History of Time')
231
author('Stephen Hawking')
232
price('15.99', currency: 'USD')
233
tags {
234
tag('physics')
235
tag('cosmology')
236
}
237
}
238
}
239
240
println writer.toString()
241
242
// Build HTML
243
def htmlWriter = new StringWriter()
244
def html = new MarkupBuilder(htmlWriter)
245
246
html.html {
247
head {
248
title('My Page')
249
meta('http-equiv': 'Content-Type', content: 'text/html; charset=UTF-8')
250
}
251
body {
252
h1('Welcome to Groovy!')
253
div(class: 'content') {
254
p('This is a paragraph with ', {
255
a('a link', href: 'http://groovy-lang.org')
256
}, '.')
257
ul {
258
['Item 1', 'Item 2', 'Item 3'].each { item ->
259
li(item)
260
}
261
}
262
}
263
}
264
}
265
266
// Build XML with namespaces
267
def nsWriter = new StringWriter()
268
def nsXml = new MarkupBuilder(nsWriter)
269
270
nsXml.'soap:Envelope'('xmlns:soap': 'http://schemas.xmlsoap.org/soap/envelope/') {
271
'soap:Header' {
272
'auth:Authentication'('xmlns:auth': 'http://example.com/auth') {
273
'auth:username'('user123')
274
'auth:token'('abc123xyz')
275
}
276
}
277
'soap:Body' {
278
'req:GetUserRequest'('xmlns:req': 'http://example.com/requests') {
279
'req:userId'(12345)
280
}
281
}
282
}
283
```
284
285
### XML Building with StreamingMarkupBuilder
286
287
Create XML with streaming for large documents.
288
289
```groovy { .api }
290
/**
291
* Streaming markup builder for large XML documents
292
*/
293
class StreamingMarkupBuilder {
294
/** Create streaming markup builder */
295
StreamingMarkupBuilder()
296
297
/** Set character encoding */
298
void setEncoding(String encoding)
299
300
/** Set whether to use double quotes for attributes */
301
void setUseDoubleQuotes(boolean useDoubleQuotes)
302
303
/** Bind closure and return writable */
304
Writable bind(Closure closure)
305
306
/** Bind closure with context */
307
Writable bind(Map context, Closure closure)
308
}
309
```
310
311
**Usage Examples:**
312
313
```groovy
314
import groovy.xml.StreamingMarkupBuilder
315
316
def builder = new StreamingMarkupBuilder()
317
builder.encoding = 'UTF-8'
318
319
def xml = builder.bind {
320
mkp.xmlDeclaration()
321
books {
322
largeDataSet.each { item ->
323
book(id: item.id) {
324
title(item.title)
325
author(item.author)
326
if (item.tags) {
327
tags {
328
item.tags.each { tag ->
329
tag(tag)
330
}
331
}
332
}
333
}
334
}
335
}
336
}
337
338
// Write to file
339
new File('large-books.xml').withWriter('UTF-8') { writer ->
340
writer << xml
341
}
342
343
// Write to HTTP response
344
response.contentType = 'application/xml'
345
response.characterEncoding = 'UTF-8'
346
response.writer << xml
347
```
348
349
### XML Utilities
350
351
Utility methods for XML processing and serialization.
352
353
```groovy { .api }
354
/**
355
* XML utility methods
356
*/
357
class XmlUtil {
358
/** Serialize Node to string */
359
static String serialize(Node node)
360
361
/** Serialize Element to string */
362
static String serialize(Element element)
363
364
/** Serialize with custom properties */
365
static String serialize(Node node, Map<String, Object> outputProperties)
366
367
/** Pretty print XML string */
368
static String prettyPrint(String xml)
369
370
/** Escape XML text */
371
static String escapeXml(String text)
372
373
/** Escape XML attribute value */
374
static String escapeControlCharacters(String text)
375
}
376
```
377
378
**Usage Examples:**
379
380
```groovy
381
import groovy.xml.XmlUtil
382
import groovy.util.XmlParser
383
384
// Parse and serialize
385
def parser = new XmlParser()
386
def root = parser.parseText('<root><child>value</child></root>')
387
388
// Serialize node to string
389
def xmlString = XmlUtil.serialize(root)
390
println xmlString
391
392
// Pretty print XML
393
def prettyXml = XmlUtil.prettyPrint(xmlString)
394
println prettyXml
395
396
// Escape XML content
397
def userInput = "Data with <tags> & \"quotes\""
398
def safeXml = XmlUtil.escapeXml(userInput)
399
println safeXml // "Data with <tags> & "quotes""
400
```
401
402
### XML Namespaces
403
404
Support for XML namespaces in parsing and building.
405
406
```groovy { .api }
407
/**
408
* Represents XML namespaces
409
*/
410
class Namespace {
411
/** Create namespace with URI */
412
Namespace(String uri)
413
414
/** Create namespace with URI and prefix */
415
Namespace(String uri, String prefix)
416
417
/** Get namespace URI */
418
String getUri()
419
420
/** Get namespace prefix */
421
String getPrefix()
422
423
/** Create qualified name */
424
QName getQName(String localName)
425
}
426
427
/**
428
* Builder supporting namespaces
429
*/
430
class NamespaceBuilder extends BuilderSupport {
431
/** Register namespace */
432
void registerNamespace(String prefix, String uri)
433
434
/** Set default namespace */
435
void setDefaultNamespace(String uri)
436
}
437
```
438
439
**Usage Examples:**
440
441
```groovy
442
import groovy.xml.Namespace
443
import groovy.xml.MarkupBuilder
444
445
// Working with namespaces in parsing
446
def nsXml = '''
447
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
448
xmlns:auth="http://example.com/auth">
449
<soap:Header>
450
<auth:Authentication>
451
<auth:username>user123</auth:username>
452
</auth:Authentication>
453
</soap:Header>
454
<soap:Body>
455
<GetUserRequest>
456
<userId>12345</userId>
457
</GetUserRequest>
458
</soap:Body>
459
</soap:Envelope>
460
'''
461
462
def slurper = new XmlSlurper().parseText(nsXml)
463
def soapNS = new Namespace('http://schemas.xmlsoap.org/soap/envelope/', 'soap')
464
def authNS = new Namespace('http://example.com/auth', 'auth')
465
466
// Access namespaced elements
467
println slurper[soapNS.Header][authNS.Authentication][authNS.username].text()
468
469
// Building with namespaces
470
def writer = new StringWriter()
471
def builder = new MarkupBuilder(writer)
472
473
def soap = new Namespace('http://schemas.xmlsoap.org/soap/envelope/', 'soap')
474
def auth = new Namespace('http://example.com/auth', 'auth')
475
476
builder."${soap.Envelope}"('xmlns:soap': soap.uri, 'xmlns:auth': auth.uri) {
477
"${soap.Header}" {
478
"${auth.Authentication}" {
479
"${auth.username}"('user123')
480
"${auth.token}"('abc123')
481
}
482
}
483
"${soap.Body}" {
484
GetUserRequest {
485
userId(12345)
486
}
487
}
488
}
489
```