XSLT Support - xmlunit/user-guide GitHub Wiki

Simplified XSLT Transformations

The org.xmlunit.transform package or Org.XmlUnit.Transform namespace contain a Transformation class that tries to hide away the complexity of javax.xml.transform (and to a lesser degree of System.Xml.Xsl).

It's main purpose inside of XMLUnit is to make testing XSLT stylesheets easier.

Something like

Source control = ...
Source test = Input.byTransforming(someInputDocument)
    .withStylesheet(sourceOfStylesheet).build();

assertThat(test, CompareMatcher.isIdenticalTo(control));

or

ISource control = ...
ISource test = Input.ByTransforming(someInputDocument)
    .WithStylesheet(sourceOfStylesheet).Build();

Assert.That(test, CompareConstraint.IsIdenticalTo(control));

can be used to easily assert that applying a certain stylesheet to a given source document yields an expected result.

The Transformation class expects a stylesheet and source and provides methods to transform to a TraX Result or .NET Stream with convenience methods for transforming to a string or DOM document. It also provides access to some features of the underlying implementation.

Transformation Builder

Transform in the builder package/namespace provides a fluent API on top of the Transformation class. A transformation of a file to a different file could be written as

StreamResult r = new StreamResult(new File(TARGET));
Transform
    .source(Input.fromFile(SOURCE).build())
    .withStylesheet(Input.fromFile(STYLESHEET).build())
    .build()
    .to(r);

or

using (FileStream fs = new FileStream(SOURCE, FileMode.OpenOrCreate, FileAccess.Write)) {
    Transform
        .Source(Input.FromFile(SOURCE).Build())
        .WithStylesheet(Input.FromFile(STYLESHEET).Build())
        .Build()
        .To(fs);
}

XXE Prevention

Whenever you parse XML there is the danger of being vulnerable to XML External Entity Processing - XXE for short.

XMLUnit for Java

The default Transformer used internally has not been configured to prevent XXE as Java's default is not safe. Starting with XMLUnit for Java 2.6.0 the Transformer is configured to not load external DTDs or entities.

This means if you want to protect yourself against XXE and you use a version of XMLUnit prior to 2.6.0 you have to explicitly set a TransformerFactory that is configured properly. Likewise if you rely on DTD loading or expansion of external entities you must provide an explicit TransformerFactory when using XMLUnit 2.6.0 or later.

XMLUnit.NET

According to OWASP's XXE Prevention Cheat Cheet the transformation's default settings should be safe.

Extension Functions

Extension functions are a way to add new functions to the XPath expressions that can be used in XSLT. These functions can invoke user provided code while executing a transformation.

If you are running transformations using untrusted stylesheets extension functions defined within could be executed - with sone XSLT processors it is even possible to define the functions inline using a scripting language.

XMLUnit for Java

JAXP's TransformerFactory by default allows the execution of extension functions and so did the default Transformer used internally prior to XMLUnit for Java 2.10.0 - this is tracked as CVE-2024-31573. Starting with 2.10.0 the default has been changed to disable extension functions.

This means if you want to protect yourself against extension functions and you use a version of XMLUnit prior to 2.10.0 you have to explicitly set a TransformerFactory that is configured properly. Likewise if you rely on extension functions you must provide an explicit TransformerFactory when using XMLUnit 2.10.0 or later.

Please see JAXP Security Guide for details.

XMLUnit.NET

XMLUnit.NET uses XslCompiledTransform internally.

This either allows extensions via a programmatic API or scripting via the msxsl:script extension element. By default suppor for msxsl:script is disabled - and it cannot be enabled on .NET Core or .NET 5 and later.

XMLUnit.NET doesn't add any extensions by default, nor does it enable msxsl:script scripts, so XSLT extensions are not enabled by default.