XMLUnit Core is a comprehensive XML testing library for Java that provides powerful tools for comparing XML documents, validating XML against schemas, and evaluating XPath expressions.
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.
The main entry point for creating XSLT transformations with fluent configuration.
public class Transform {
/**
* Create transformation builder for source document
* @param s - Source document to transform
* @returns Builder instance for configuring transformation
*/
public static Builder source(Source s);
}
public interface Builder extends TransformationBuilderBase<Builder> {
/** Build the transformation result */
TransformationResult build();
}
public interface TransformationResult {
/** Output the result to a TraX Result */
void to(Result r);
/** Output the result to a String */
String toString();
/** Output the result to a DOM Document */
Document toDocument();
}Comprehensive configuration options for XSLT transformations.
public interface TransformationBuilderBase<T> {
/** Apply XSLT stylesheet to transformation */
T usingStylesheet(Source stylesheet);
/** Set XSLT parameter for transformation */
T withParameter(String name, Object value);
/** Set output property for transformation result */
T withOutputProperty(String name, String value);
/** Configure custom TransformerFactory */
T withTransformerFactory(TransformerFactory factory);
/** Set URI resolver for resolving document() and import/include */
T withURIResolver(URIResolver resolver);
}Usage Examples:
import org.xmlunit.builder.Transform;
import org.xmlunit.builder.Input;
import javax.xml.transform.Source;
import javax.xml.transform.OutputKeys;
// Basic XSLT transformation
Source xmlSource = Input.fromString("""
<catalog>
<book id="1">
<title>Java Programming</title>
<author>John Smith</author>
<price>29.99</price>
</book>
<book id="2">
<title>XML Processing</title>
<author>Jane Doe</author>
<price>34.99</price>
</book>
</catalog>
""").build();
Source stylesheetSource = Input.fromString("""
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h1>Book Catalog</h1>
<xsl:for-each select="catalog/book">
<div>
<h2><xsl:value-of select="title"/></h2>
<p>Author: <xsl:value-of select="author"/></p>
<p>Price: $<xsl:value-of select="price"/></p>
</div>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
""").build();
// Transform XML to HTML
Source htmlResult = Transform.source(xmlSource)
.usingStylesheet(stylesheetSource)
.withOutputProperty(OutputKeys.METHOD, "html")
.withOutputProperty(OutputKeys.INDENT, "yes")
.build();
// Use the transformed result (htmlResult is now an HTML document)Pass parameters to XSLT stylesheets for dynamic transformations.
/** Set XSLT parameter for transformation */
T withParameter(String name, Object value);Parameter Examples:
// XSLT stylesheet with parameters
Source stylesheetWithParams = Input.fromString("""
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="title" select="'Default Title'"/>
<xsl:param name="maxPrice" select="100"/>
<xsl:param name="showPrices" select="'true'"/>
<xsl:template match="/">
<html>
<body>
<h1><xsl:value-of select="$title"/></h1>
<xsl:for-each select="catalog/book[price <= $maxPrice]">
<div>
<h2><xsl:value-of select="title"/></h2>
<p>Author: <xsl:value-of select="author"/></p>
<xsl:if test="$showPrices = 'true'">
<p>Price: $<xsl:value-of select="price"/></p>
</xsl:if>
</div>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
""").build();
// Transform with parameters
Source parameterizedResult = Transform.source(xmlSource)
.usingStylesheet(stylesheetWithParams)
.withParameter("title", "Affordable Books")
.withParameter("maxPrice", 30.0)
.withParameter("showPrices", "false")
.withOutputProperty(OutputKeys.METHOD, "html")
.withOutputProperty(OutputKeys.INDENT, "yes")
.build();
// Parameters can be various Java types
Source multiTypeParams = Transform.source(xmlSource)
.usingStylesheet(stylesheetWithParams)
.withParameter("title", "Book Catalog") // String
.withParameter("maxPrice", Integer.valueOf(50)) // Integer
.withParameter("showPrices", Boolean.TRUE) // Boolean
.withParameter("discount", 0.15) // Double
.build();Configure transformation output format and properties.
/** Set output property for transformation result */
T withOutputProperty(String name, String value);Output Property Examples:
import javax.xml.transform.OutputKeys;
// HTML output with formatting
Source htmlOutput = Transform.source(xmlSource)
.usingStylesheet(stylesheetSource)
.withOutputProperty(OutputKeys.METHOD, "html")
.withOutputProperty(OutputKeys.INDENT, "yes")
.withOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "-//W3C//DTD HTML 4.01//EN")
.withOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "http://www.w3.org/TR/html4/strict.dtd")
.build();
// XML output with encoding
Source xmlOutput = Transform.source(xmlSource)
.usingStylesheet(stylesheetSource)
.withOutputProperty(OutputKeys.METHOD, "xml")
.withOutputProperty(OutputKeys.ENCODING, "UTF-8")
.withOutputProperty(OutputKeys.STANDALONE, "yes")
.withOutputProperty(OutputKeys.INDENT, "yes")
.withOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2")
.build();
// Text output
Source textOutput = Transform.source(xmlSource)
.usingStylesheet(textStylesheet)
.withOutputProperty(OutputKeys.METHOD, "text")
.withOutputProperty(OutputKeys.ENCODING, "UTF-8")
.build();
// Custom output properties (XSLT processor specific)
Source customOutput = Transform.source(xmlSource)
.usingStylesheet(stylesheetSource)
.withOutputProperty("custom-property", "custom-value")
.build();Configure TransformerFactory and URI resolution for complex scenarios.
/** Configure custom TransformerFactory */
T withTransformerFactory(TransformerFactory factory);
/** Set URI resolver for resolving document() and import/include */
T withURIResolver(URIResolver resolver);Advanced Configuration Examples:
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
// Custom TransformerFactory configuration
TransformerFactory customFactory = TransformerFactory.newInstance();
customFactory.setAttribute("javax.xml.transform.disable-output-escaping", Boolean.FALSE);
Source customFactoryResult = Transform.source(xmlSource)
.usingStylesheet(stylesheetSource)
.withTransformerFactory(customFactory)
.build();
// Custom URI resolver for stylesheet imports and document() function
URIResolver customResolver = new URIResolver() {
@Override
public Source resolve(String href, String base) throws TransformerException {
if (href.startsWith("classpath:")) {
String resourcePath = href.substring("classpath:".length());
InputStream stream = getClass().getResourceAsStream(resourcePath);
if (stream != null) {
return new StreamSource(stream);
}
}
return null; // Use default resolution
}
};
Source resolverResult = Transform.source(xmlSource)
.usingStylesheet(stylesheetSource)
.withURIResolver(customResolver)
.build();Apply multiple transformations in sequence for complex processing pipelines.
// Multi-stage transformation pipeline
Source stage1 = Transform.source(originalXml)
.usingStylesheet(Input.fromFile("normalize.xsl").build())
.withParameter("version", "1.0")
.build();
Source stage2 = Transform.source(stage1)
.usingStylesheet(Input.fromFile("enrich.xsl").build())
.withParameter("enrichmentData", enrichmentSource)
.build();
Source finalResult = Transform.source(stage2)
.usingStylesheet(Input.fromFile("format.xsl").build())
.withOutputProperty(OutputKeys.INDENT, "yes")
.build();
// Or using Input.byTransforming for direct chaining
Source chainedResult = Input.byTransforming(
Input.byTransforming(originalXml)
.usingStylesheet(Input.fromFile("step1.xsl").build())
)
.usingStylesheet(Input.fromFile("step2.xsl").build())
.build();Use transformed sources with other XMLUnit components.
// Transform and validate result
Source transformedXml = Transform.source(inputXml)
.usingStylesheet(transformStylesheet)
.build();
Validator validator = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI);
validator.setSchemaSource(Input.fromFile("output-schema.xsd").build());
ValidationResult validationResult = validator.validateInstance(transformedXml);
// Transform and compare with expected result
Source expectedXml = Input.fromFile("expected-output.xml").build();
Diff diff = DiffBuilder.compare(expectedXml)
.withTest(transformedXml)
.ignoreWhitespace()
.build();
// Transform and evaluate XPath on result
JAXPXPathEngine xpath = new JAXPXPathEngine();
String resultValue = xpath.evaluate("//result/value/text()", transformedXml);
// Transform for different output formats in same operation
Source htmlVersion = Transform.source(dataXml)
.usingStylesheet(htmlStylesheet)
.withOutputProperty(OutputKeys.METHOD, "html")
.build();
Source pdfVersion = Transform.source(dataXml)
.usingStylesheet(pdfStylesheet)
.withOutputProperty(OutputKeys.METHOD, "xml")
.build();Handle transformation errors and configuration issues.
try {
Source result = Transform.source(xmlSource)
.usingStylesheet(stylesheetSource)
.withParameter("param1", "value1")
.build();
} catch (RuntimeException e) {
// Handle transformation errors
if (e.getCause() instanceof TransformerException) {
System.err.println("XSLT transformation failed: " + e.getMessage());
} else if (e.getCause() instanceof TransformerConfigurationException) {
System.err.println("XSLT configuration error: " + e.getMessage());
} else {
System.err.println("Transformation error: " + e.getMessage());
}
}
// Handle stylesheet compilation errors
try {
Source invalidStylesheet = Input.fromString("<invalid>xslt</invalid>").build();
Source result = Transform.source(xmlSource)
.usingStylesheet(invalidStylesheet)
.build();
} catch (RuntimeException e) {
System.err.println("Invalid stylesheet: " + e.getMessage());
}Frequently used transformation scenarios and examples.
Data Format Conversion:
// XML to JSON-like structure
Source xmlToJson = Transform.source(xmlData)
.usingStylesheet(Input.fromFile("xml-to-json.xsl").build())
.withOutputProperty(OutputKeys.METHOD, "text")
.build();
// XML to CSV
Source xmlToCsv = Transform.source(xmlData)
.usingStylesheet(Input.fromFile("xml-to-csv.xsl").build())
.withOutputProperty(OutputKeys.METHOD, "text")
.build();Document Restructuring:
// Flatten nested structure
Source flattened = Transform.source(nestedXml)
.usingStylesheet(Input.fromFile("flatten.xsl").build())
.build();
// Group and sort elements
Source grouped = Transform.source(unsortedXml)
.usingStylesheet(Input.fromFile("group-sort.xsl").build())
.withParameter("sortBy", "name")
.withParameter("groupBy", "category")
.build();Content Filtering:
// Filter by criteria
Source filtered = Transform.source(fullDataXml)
.usingStylesheet(Input.fromFile("filter.xsl").build())
.withParameter("minDate", "2023-01-01")
.withParameter("status", "active")
.build();
// Remove sensitive information
Source sanitized = Transform.source(sensitiveXml)
.usingStylesheet(Input.fromFile("sanitize.xsl").build())
.withParameter("removePersonalData", true)
.build();Report Generation:
// Generate HTML report
Source htmlReport = Transform.source(dataXml)
.usingStylesheet(Input.fromFile("report.xsl").build())
.withParameter("reportTitle", "Monthly Summary")
.withParameter("reportDate", new Date())
.withOutputProperty(OutputKeys.METHOD, "html")
.withOutputProperty(OutputKeys.INDENT, "yes")
.build();
// Generate summary statistics
Source summary = Transform.source(detailedXml)
.usingStylesheet(Input.fromFile("summarize.xsl").build())
.withParameter("groupByField", "department")
.build();Transformation works seamlessly with all XMLUnit input source types.
// Transform from various sources
Source fileTransform = Transform.source(Input.fromFile("data.xml").build())
.usingStylesheet(Input.fromFile("transform.xsl").build())
.build();
Source stringTransform = Transform.source(Input.fromString(xmlString).build())
.usingStylesheet(Input.fromString(xsltString).build())
.build();
Source urlTransform = Transform.source(Input.fromURL(dataUrl).build())
.usingStylesheet(Input.fromURL(styleUrl).build())
.build();
Source jaxbTransform = Transform.source(Input.fromJaxb(jaxbObject).build())
.usingStylesheet(Input.fromFile("jaxb-to-html.xsl").build())
.build();
// Transform chained with other Input operations
Source complexTransform = Transform.source(
Input.byTransforming(Input.fromFile("raw-data.xml").build())
.usingStylesheet(Input.fromFile("preprocess.xsl").build())
)
.usingStylesheet(Input.fromFile("final-transform.xsl").build())
.build();Install with Tessl CLI
npx tessl i tessl/maven-org-xmlunit--xmlunit-core