javaxmljaxbdocx4jjavax

Doc4j: Compare two documents fails due to different Element-types


I try to write some JUnit tests for a Docx4J generator I have written. I want to compare the output node of my generator with an expected node that I want to load from a string.

So, I create my "actual" node (generator output) like so:

Node xmlNodeActual = XmlUtils.marshaltoW3CDomDocument(actual).getDocumentElement();

Where "actual" is the Object that was created by my generator.

For my "expected" node, I have written the following code:

Document doc = docBuilder.parse(new InputSource(new ByteArrayInputStream(strXmlNode.getBytes("utf-8")))):
Node xmlNodeExpected = doc.getDocumentElement();

strXmlNode is a string holding the expected xml. Although my two nodes are equal as far as I can tell from a visual diff, calling the following yields 'false' as a result:

xmlNodeActual.isEqualNode(xmlNodeExpected)

I suspect the reason is that the runtime types of the two nodes differ:

I like my test design since it would allow me to write a lot of test cases rather quickly for a large generator. However, I don't see a way to utilize this approach in combination with "isEqualNode". Do I have to write my own comparer or is there a way I am not aware of to make sure the types of the nodes are the same?


Solution

  • Notice that @Michael Kay and @JasonPlutext contributed interesting and better alternatives on how to test XML output in general, which you might want to consider.

    As for my specific question and problem, i.e. trivially comparing two XML nodes with "isEqualNode", one stemming from a input string, one stemming from data transformation, I had to do the following: Instead of parsing the string, I can unmarshal it via a InputStream, thus getting the desired node types.

    // creating the "actual" node I want to test (nothing changed here)
    Node xmlNodeActual = XmlUtils.marshaltoW3CDomDocument(actual).getDocumentElement();
    
    //...
    
    // Instead of parsing the string, just unmarshal and marshal it once
    Object expected = XmlUtils.unmarshal(new ByteArrayInputStream(strXmlNode.getBytes("utf-8")));
    Node xmlNodeExpected = XmlUtils.marshaltoW3CDomDocument(expected).getDocumentElement();
    if(!xmlNodeActual.isEqualNode(xmlNodeExpected)) {
    // ...
    }
    

    This produces the same node types and works for my setup as expected. Still, this way of comparing two XML trees has several flaws as has been pointed out by Michael Kay, so don't consider this a best practice and rather resort to another answer for general XML comparison.