0
# XSLT Transformation
1
2
XSLT stylesheet transformation utilities with parameter support, custom URI resolvers, and flexible output configuration for transforming XML documents. XMLUnit provides a fluent API for applying XSLT transformations to XML sources.
3
4
## Capabilities
5
6
### Transform Builder
7
8
The main entry point for creating XSLT transformations with fluent configuration.
9
10
```java { .api }
11
public class Transform {
12
/**
13
* Create transformation builder for source document
14
* @param s - Source document to transform
15
* @returns Builder instance for configuring transformation
16
*/
17
public static Builder source(Source s);
18
}
19
20
public interface Builder extends TransformationBuilderBase<Builder> {
21
/** Build the transformation result */
22
TransformationResult build();
23
}
24
25
public interface TransformationResult {
26
/** Output the result to a TraX Result */
27
void to(Result r);
28
29
/** Output the result to a String */
30
String toString();
31
32
/** Output the result to a DOM Document */
33
Document toDocument();
34
}
35
```
36
37
### Transformation Configuration
38
39
Comprehensive configuration options for XSLT transformations.
40
41
```java { .api }
42
public interface TransformationBuilderBase<T> {
43
/** Apply XSLT stylesheet to transformation */
44
T usingStylesheet(Source stylesheet);
45
46
/** Set XSLT parameter for transformation */
47
T withParameter(String name, Object value);
48
49
/** Set output property for transformation result */
50
T withOutputProperty(String name, String value);
51
52
/** Configure custom TransformerFactory */
53
T withTransformerFactory(TransformerFactory factory);
54
55
/** Set URI resolver for resolving document() and import/include */
56
T withURIResolver(URIResolver resolver);
57
}
58
```
59
60
**Usage Examples:**
61
62
```java
63
import org.xmlunit.builder.Transform;
64
import org.xmlunit.builder.Input;
65
import javax.xml.transform.Source;
66
import javax.xml.transform.OutputKeys;
67
68
// Basic XSLT transformation
69
Source xmlSource = Input.fromString("""
70
<catalog>
71
<book id="1">
72
<title>Java Programming</title>
73
<author>John Smith</author>
74
<price>29.99</price>
75
</book>
76
<book id="2">
77
<title>XML Processing</title>
78
<author>Jane Doe</author>
79
<price>34.99</price>
80
</book>
81
</catalog>
82
""").build();
83
84
Source stylesheetSource = Input.fromString("""
85
<?xml version="1.0"?>
86
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
87
<xsl:template match="/">
88
<html>
89
<body>
90
<h1>Book Catalog</h1>
91
<xsl:for-each select="catalog/book">
92
<div>
93
<h2><xsl:value-of select="title"/></h2>
94
<p>Author: <xsl:value-of select="author"/></p>
95
<p>Price: $<xsl:value-of select="price"/></p>
96
</div>
97
</xsl:for-each>
98
</body>
99
</html>
100
</xsl:template>
101
</xsl:stylesheet>
102
""").build();
103
104
// Transform XML to HTML
105
Source htmlResult = Transform.source(xmlSource)
106
.usingStylesheet(stylesheetSource)
107
.withOutputProperty(OutputKeys.METHOD, "html")
108
.withOutputProperty(OutputKeys.INDENT, "yes")
109
.build();
110
111
// Use the transformed result (htmlResult is now an HTML document)
112
```
113
114
### Parameter Support
115
116
Pass parameters to XSLT stylesheets for dynamic transformations.
117
118
```java { .api }
119
/** Set XSLT parameter for transformation */
120
T withParameter(String name, Object value);
121
```
122
123
**Parameter Examples:**
124
125
```java
126
// XSLT stylesheet with parameters
127
Source stylesheetWithParams = Input.fromString("""
128
<?xml version="1.0"?>
129
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
130
<xsl:param name="title" select="'Default Title'"/>
131
<xsl:param name="maxPrice" select="100"/>
132
<xsl:param name="showPrices" select="'true'"/>
133
134
<xsl:template match="/">
135
<html>
136
<body>
137
<h1><xsl:value-of select="$title"/></h1>
138
<xsl:for-each select="catalog/book[price <= $maxPrice]">
139
<div>
140
<h2><xsl:value-of select="title"/></h2>
141
<p>Author: <xsl:value-of select="author"/></p>
142
<xsl:if test="$showPrices = 'true'">
143
<p>Price: $<xsl:value-of select="price"/></p>
144
</xsl:if>
145
</div>
146
</xsl:for-each>
147
</body>
148
</html>
149
</xsl:template>
150
</xsl:stylesheet>
151
""").build();
152
153
// Transform with parameters
154
Source parameterizedResult = Transform.source(xmlSource)
155
.usingStylesheet(stylesheetWithParams)
156
.withParameter("title", "Affordable Books")
157
.withParameter("maxPrice", 30.0)
158
.withParameter("showPrices", "false")
159
.withOutputProperty(OutputKeys.METHOD, "html")
160
.withOutputProperty(OutputKeys.INDENT, "yes")
161
.build();
162
163
// Parameters can be various Java types
164
Source multiTypeParams = Transform.source(xmlSource)
165
.usingStylesheet(stylesheetWithParams)
166
.withParameter("title", "Book Catalog") // String
167
.withParameter("maxPrice", Integer.valueOf(50)) // Integer
168
.withParameter("showPrices", Boolean.TRUE) // Boolean
169
.withParameter("discount", 0.15) // Double
170
.build();
171
```
172
173
### Output Properties
174
175
Configure transformation output format and properties.
176
177
```java { .api }
178
/** Set output property for transformation result */
179
T withOutputProperty(String name, String value);
180
```
181
182
**Output Property Examples:**
183
184
```java
185
import javax.xml.transform.OutputKeys;
186
187
// HTML output with formatting
188
Source htmlOutput = Transform.source(xmlSource)
189
.usingStylesheet(stylesheetSource)
190
.withOutputProperty(OutputKeys.METHOD, "html")
191
.withOutputProperty(OutputKeys.INDENT, "yes")
192
.withOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "-//W3C//DTD HTML 4.01//EN")
193
.withOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "http://www.w3.org/TR/html4/strict.dtd")
194
.build();
195
196
// XML output with encoding
197
Source xmlOutput = Transform.source(xmlSource)
198
.usingStylesheet(stylesheetSource)
199
.withOutputProperty(OutputKeys.METHOD, "xml")
200
.withOutputProperty(OutputKeys.ENCODING, "UTF-8")
201
.withOutputProperty(OutputKeys.STANDALONE, "yes")
202
.withOutputProperty(OutputKeys.INDENT, "yes")
203
.withOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2")
204
.build();
205
206
// Text output
207
Source textOutput = Transform.source(xmlSource)
208
.usingStylesheet(textStylesheet)
209
.withOutputProperty(OutputKeys.METHOD, "text")
210
.withOutputProperty(OutputKeys.ENCODING, "UTF-8")
211
.build();
212
213
// Custom output properties (XSLT processor specific)
214
Source customOutput = Transform.source(xmlSource)
215
.usingStylesheet(stylesheetSource)
216
.withOutputProperty("custom-property", "custom-value")
217
.build();
218
```
219
220
### Advanced Configuration
221
222
Configure TransformerFactory and URI resolution for complex scenarios.
223
224
```java { .api }
225
/** Configure custom TransformerFactory */
226
T withTransformerFactory(TransformerFactory factory);
227
228
/** Set URI resolver for resolving document() and import/include */
229
T withURIResolver(URIResolver resolver);
230
```
231
232
**Advanced Configuration Examples:**
233
234
```java
235
import javax.xml.transform.TransformerFactory;
236
import javax.xml.transform.URIResolver;
237
import javax.xml.transform.Source;
238
import javax.xml.transform.stream.StreamSource;
239
240
// Custom TransformerFactory configuration
241
TransformerFactory customFactory = TransformerFactory.newInstance();
242
customFactory.setAttribute("javax.xml.transform.disable-output-escaping", Boolean.FALSE);
243
244
Source customFactoryResult = Transform.source(xmlSource)
245
.usingStylesheet(stylesheetSource)
246
.withTransformerFactory(customFactory)
247
.build();
248
249
// Custom URI resolver for stylesheet imports and document() function
250
URIResolver customResolver = new URIResolver() {
251
@Override
252
public Source resolve(String href, String base) throws TransformerException {
253
if (href.startsWith("classpath:")) {
254
String resourcePath = href.substring("classpath:".length());
255
InputStream stream = getClass().getResourceAsStream(resourcePath);
256
if (stream != null) {
257
return new StreamSource(stream);
258
}
259
}
260
return null; // Use default resolution
261
}
262
};
263
264
Source resolverResult = Transform.source(xmlSource)
265
.usingStylesheet(stylesheetSource)
266
.withURIResolver(customResolver)
267
.build();
268
```
269
270
### Chained Transformations
271
272
Apply multiple transformations in sequence for complex processing pipelines.
273
274
```java
275
// Multi-stage transformation pipeline
276
Source stage1 = Transform.source(originalXml)
277
.usingStylesheet(Input.fromFile("normalize.xsl").build())
278
.withParameter("version", "1.0")
279
.build();
280
281
Source stage2 = Transform.source(stage1)
282
.usingStylesheet(Input.fromFile("enrich.xsl").build())
283
.withParameter("enrichmentData", enrichmentSource)
284
.build();
285
286
Source finalResult = Transform.source(stage2)
287
.usingStylesheet(Input.fromFile("format.xsl").build())
288
.withOutputProperty(OutputKeys.INDENT, "yes")
289
.build();
290
291
// Or using Input.byTransforming for direct chaining
292
Source chainedResult = Input.byTransforming(
293
Input.byTransforming(originalXml)
294
.usingStylesheet(Input.fromFile("step1.xsl").build())
295
)
296
.usingStylesheet(Input.fromFile("step2.xsl").build())
297
.build();
298
```
299
300
### Transformation Result Usage
301
302
Use transformed sources with other XMLUnit components.
303
304
```java
305
// Transform and validate result
306
Source transformedXml = Transform.source(inputXml)
307
.usingStylesheet(transformStylesheet)
308
.build();
309
310
Validator validator = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI);
311
validator.setSchemaSource(Input.fromFile("output-schema.xsd").build());
312
ValidationResult validationResult = validator.validateInstance(transformedXml);
313
314
// Transform and compare with expected result
315
Source expectedXml = Input.fromFile("expected-output.xml").build();
316
Diff diff = DiffBuilder.compare(expectedXml)
317
.withTest(transformedXml)
318
.ignoreWhitespace()
319
.build();
320
321
// Transform and evaluate XPath on result
322
JAXPXPathEngine xpath = new JAXPXPathEngine();
323
String resultValue = xpath.evaluate("//result/value/text()", transformedXml);
324
325
// Transform for different output formats in same operation
326
Source htmlVersion = Transform.source(dataXml)
327
.usingStylesheet(htmlStylesheet)
328
.withOutputProperty(OutputKeys.METHOD, "html")
329
.build();
330
331
Source pdfVersion = Transform.source(dataXml)
332
.usingStylesheet(pdfStylesheet)
333
.withOutputProperty(OutputKeys.METHOD, "xml")
334
.build();
335
```
336
337
### Error Handling
338
339
Handle transformation errors and configuration issues.
340
341
```java
342
try {
343
Source result = Transform.source(xmlSource)
344
.usingStylesheet(stylesheetSource)
345
.withParameter("param1", "value1")
346
.build();
347
348
} catch (RuntimeException e) {
349
// Handle transformation errors
350
if (e.getCause() instanceof TransformerException) {
351
System.err.println("XSLT transformation failed: " + e.getMessage());
352
} else if (e.getCause() instanceof TransformerConfigurationException) {
353
System.err.println("XSLT configuration error: " + e.getMessage());
354
} else {
355
System.err.println("Transformation error: " + e.getMessage());
356
}
357
}
358
359
// Handle stylesheet compilation errors
360
try {
361
Source invalidStylesheet = Input.fromString("<invalid>xslt</invalid>").build();
362
363
Source result = Transform.source(xmlSource)
364
.usingStylesheet(invalidStylesheet)
365
.build();
366
367
} catch (RuntimeException e) {
368
System.err.println("Invalid stylesheet: " + e.getMessage());
369
}
370
```
371
372
### Common Transformation Patterns
373
374
Frequently used transformation scenarios and examples.
375
376
**Data Format Conversion:**
377
```java
378
// XML to JSON-like structure
379
Source xmlToJson = Transform.source(xmlData)
380
.usingStylesheet(Input.fromFile("xml-to-json.xsl").build())
381
.withOutputProperty(OutputKeys.METHOD, "text")
382
.build();
383
384
// XML to CSV
385
Source xmlToCsv = Transform.source(xmlData)
386
.usingStylesheet(Input.fromFile("xml-to-csv.xsl").build())
387
.withOutputProperty(OutputKeys.METHOD, "text")
388
.build();
389
```
390
391
**Document Restructuring:**
392
```java
393
// Flatten nested structure
394
Source flattened = Transform.source(nestedXml)
395
.usingStylesheet(Input.fromFile("flatten.xsl").build())
396
.build();
397
398
// Group and sort elements
399
Source grouped = Transform.source(unsortedXml)
400
.usingStylesheet(Input.fromFile("group-sort.xsl").build())
401
.withParameter("sortBy", "name")
402
.withParameter("groupBy", "category")
403
.build();
404
```
405
406
**Content Filtering:**
407
```java
408
// Filter by criteria
409
Source filtered = Transform.source(fullDataXml)
410
.usingStylesheet(Input.fromFile("filter.xsl").build())
411
.withParameter("minDate", "2023-01-01")
412
.withParameter("status", "active")
413
.build();
414
415
// Remove sensitive information
416
Source sanitized = Transform.source(sensitiveXml)
417
.usingStylesheet(Input.fromFile("sanitize.xsl").build())
418
.withParameter("removePersonalData", true)
419
.build();
420
```
421
422
**Report Generation:**
423
```java
424
// Generate HTML report
425
Source htmlReport = Transform.source(dataXml)
426
.usingStylesheet(Input.fromFile("report.xsl").build())
427
.withParameter("reportTitle", "Monthly Summary")
428
.withParameter("reportDate", new Date())
429
.withOutputProperty(OutputKeys.METHOD, "html")
430
.withOutputProperty(OutputKeys.INDENT, "yes")
431
.build();
432
433
// Generate summary statistics
434
Source summary = Transform.source(detailedXml)
435
.usingStylesheet(Input.fromFile("summarize.xsl").build())
436
.withParameter("groupByField", "department")
437
.build();
438
```
439
440
### Integration with Input Sources
441
442
Transformation works seamlessly with all XMLUnit input source types.
443
444
```java
445
// Transform from various sources
446
Source fileTransform = Transform.source(Input.fromFile("data.xml").build())
447
.usingStylesheet(Input.fromFile("transform.xsl").build())
448
.build();
449
450
Source stringTransform = Transform.source(Input.fromString(xmlString).build())
451
.usingStylesheet(Input.fromString(xsltString).build())
452
.build();
453
454
Source urlTransform = Transform.source(Input.fromURL(dataUrl).build())
455
.usingStylesheet(Input.fromURL(styleUrl).build())
456
.build();
457
458
Source jaxbTransform = Transform.source(Input.fromJaxb(jaxbObject).build())
459
.usingStylesheet(Input.fromFile("jaxb-to-html.xsl").build())
460
.build();
461
462
// Transform chained with other Input operations
463
Source complexTransform = Transform.source(
464
Input.byTransforming(Input.fromFile("raw-data.xml").build())
465
.usingStylesheet(Input.fromFile("preprocess.xsl").build())
466
)
467
.usingStylesheet(Input.fromFile("final-transform.xsl").build())
468
.build();
469
```