Skip to content

XMLUnit with Java 9 and above

Stefan Bodewig edited this page Jul 28, 2019 · 1 revision

XMLUnit with Java 9 and above

This page gathers the things that you need to know if you want to run XMLUnit apps on Java 9 and above.

javax.xml.transform.Transformer changes

With Java 9 the Transformer class behavior is different from previous versions.

Let's see it with and example:

<?xml version="1.0" encoding="UTF-8"?>
<notification>
    <to>[email protected]</to>
    <info><![CDATA[update]]></info>
</notification>

And store in a input String variable. To process with the transformer:

StreamSource source = new StreamSource(new StringReader(input));
Transformer transformer = TransformerFactory
  .newInstance()
  .newTransformer();

transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StreamResult result = new StreamResult(new StringWriter());
transformer.transform(source, result);
String output = result
  .getWriter()
  .toString();

If we tried to compare using xmlunit-assertj areSimilar() function:

assertThat(input)
  .and(output)
  .areSimilar();

In Java 8 it will pass, but with Java 9 and above we'll get the following differences:

java.lang.AssertionError: 
Expecting:
 <<notification>
    <to>[email protected]</to>
    <info><![CDATA[update]]></info>
</notification>>
to be equal to:
 <<notification>
␣␣␣␣␣␣␣␣
    <to>[email protected]</to>
␣␣␣␣␣␣␣␣
    <info>
␣␣␣␣␣␣␣␣<![CDATA[update]]>
    </info>
␣␣␣␣
</notification>>
but was not.
  1. Extra newlines with spaces between elements.
  2. The elements with CDATA are in new lines with spaces. (This issue has been fixed in Java 14. Tested it with the 14-ea+6-171 build)

Both cases are known issues related to the changes in the JDK. We can found more details here https://github.com/CodeFX-org/java-9-wtf/tree/master/xml-transformer, https://stackoverflow.com/questions/55853220/handling-change-in-newlines-by-xml-transformation-for-cdata-from-java-8-to-java, and https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8223291.

In order to mitigate them, we can use the replaceAll() function with a regex:

  1. To remove the additional new lines: output.replaceAll("(?m)^[ \t]*\r?\n", "");
  2. To remove the newline between the CDATA tag: xml.replaceAll(">\\s*(<\\!\\[CDATA\\[.*?]]>)\\s*</", ">$1</");