diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 8c9af748..b2889996 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -31,6 +31,10 @@ * `Input` builder now supports `java.nio.file.Path` [#196](https://github.com/xmlunit/xmlunit/issues/196) +* It is now possible to specify a custom `TransformerFactory` for + `DefaultComparisonFormatter`. + [#195](https://github.com/xmlunit/xmlunit/issues/195) + ## XMLUnit for Java 2.7.0 - /Released 2020-05-12/ This version contains a backwards incompatible change to the diff --git a/xmlunit-core/src/main/java/org/xmlunit/diff/DefaultComparisonFormatter.java b/xmlunit-core/src/main/java/org/xmlunit/diff/DefaultComparisonFormatter.java index be31a4bd..c55710af 100644 --- a/xmlunit-core/src/main/java/org/xmlunit/diff/DefaultComparisonFormatter.java +++ b/xmlunit-core/src/main/java/org/xmlunit/diff/DefaultComparisonFormatter.java @@ -42,6 +42,8 @@ */ public class DefaultComparisonFormatter implements ComparisonFormatter { + private TransformerFactory factory; + /** * Return a short String of the Comparison including the XPath and the shorten value of the effected control and * test Node. @@ -81,6 +83,17 @@ public String getDescription(Comparison difference) { controlTarget, testTarget); } + /** + * Set the TraX factory to use. + * + * @param f the factory to use - may be null in which case the + * default factory will be used. + * @since 2.8.0 + */ + public void setTransformerFactory(final TransformerFactory f) { + factory = f; + } + /** * May alter the display of a comparison value for {@link #getShortString} based on the comparison type. * @@ -453,16 +466,19 @@ protected String getFormattedNodeXml(final Node nodeToConvert, boolean formatXml * @since XMLUnit 2.4.0 */ protected Transformer createXmlTransformer(int numberOfBlanksToIndent) throws TransformerConfigurationException { - TransformerFactoryConfigurer.Builder b = TransformerFactoryConfigurer.builder() - .withExternalStylesheetLoadingDisabled() - .withDTDLoadingDisabled(); - - if (numberOfBlanksToIndent >= 0) { - // not all TransformerFactories support this feature - b = b.withSafeAttribute("indent-number", numberOfBlanksToIndent); + TransformerFactory fac = factory; + if (fac == null) { + TransformerFactoryConfigurer.Builder b = TransformerFactoryConfigurer.builder() + .withExternalStylesheetLoadingDisabled() + .withDTDLoadingDisabled(); + + if (numberOfBlanksToIndent >= 0) { + // not all TransformerFactories support this feature + b = b.withSafeAttribute("indent-number", numberOfBlanksToIndent); + } + fac = b.build().configure(TransformerFactory.newInstance()); } - final TransformerFactory factory = b.build().configure(TransformerFactory.newInstance()); - final Transformer transformer = factory.newTransformer(); + final Transformer transformer = fac.newTransformer(); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); if (numberOfBlanksToIndent >= 0) { diff --git a/xmlunit-core/src/test/java/org/xmlunit/diff/DefaultComparisonFormatterTest.java b/xmlunit-core/src/test/java/org/xmlunit/diff/DefaultComparisonFormatterTest.java index 6dfc87e3..400f00f4 100644 --- a/xmlunit-core/src/test/java/org/xmlunit/diff/DefaultComparisonFormatterTest.java +++ b/xmlunit-core/src/test/java/org/xmlunit/diff/DefaultComparisonFormatterTest.java @@ -17,6 +17,8 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import org.xmlunit.builder.DiffBuilder; import org.xmlunit.builder.Input; @@ -24,32 +26,36 @@ import org.junit.Assert; import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.w3c.dom.Document; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; - +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactory; public class DefaultComparisonFormatterTest { private DefaultComparisonFormatter compFormatter = new DefaultComparisonFormatter(); + @Mock + private TransformerFactory fac; + private static final boolean JAVA_9_PLUS, JAVA_14_PLUS; static { boolean j9 = false; try { Class.forName("java.lang.module.ModuleDescriptor"); j9 = true; - } catch (ClassNotFoundException e) { - } catch (Error e) { + } catch (ClassNotFoundException | Error e) { } JAVA_9_PLUS = j9; boolean j14 = false; try { Class.forName("java.lang.reflect.RecordComponent"); j14 = true; - } catch (ClassNotFoundException e) { - } catch (Error e) { + } catch (ClassNotFoundException | Error e) { } JAVA_14_PLUS = j14; } @@ -639,6 +645,20 @@ public void testComparisonType_WhitespacesAndUnformattedDetails() { assertEquals("\n \n", testDetailsUnformatted); } + @Test + public void usesCustomTransformerFactory() throws TransformerConfigurationException { + Diff diff = DiffBuilder.compare("").withTest("\n \n").build(); + Comparison firstDiff = diff.getDifferences().iterator().next().getComparison(); + + MockitoAnnotations.initMocks(this); + when(fac.newTransformer()) + .thenReturn(TransformerFactory.newInstance().newTransformer()); + + compFormatter.setTransformerFactory(fac); + getDetails(firstDiff.getControlDetails(), firstDiff.getType()); + verify(fac).newTransformer(); + } + private DocumentBuilderFactory getDocumentBuilderFactoryWithoutValidation() throws ParserConfigurationException { // code snippet from http://stackoverflow.com/a/155874/702345 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();