Skip to content

NullPointerException when comparing elements with null attributes #307

@dzik-darek

Description

@dzik-darek

Summary

When comparing XML documents containing attributes with null values, NullPointerException is thrown.

Steps to reproduce

Test code below should trigger the NPE:

@Test
void testSetAttribute_whenNull_shouldBeEmptyAttribute() throws ParserConfigurationException {
    // given
    Document document = DocumentBuilderFactory.newInstance()
            .newDocumentBuilder()
            .newDocument();

    // when
    Element element = document.createElement("Tag");
    element.setAttribute("name", null);
    document.appendChild(element);

    // then
    assertThat(document)
            .and(Input.fromString("<Tag name=\"\"></Tag>"))
            .areIdentical();
}

Actual behavior

AssertionError is thrown with:
org.xmlunit.XMLUnitException: Caught exception during comparison at org.xmlunit.diff.DOMDifferenceEngine.compare(DOMDifferenceEngine.java:120),

which under the hood is
ava.lang.NullPointerException: Cannot invoke "org.w3c.dom.Node.getNodeType()" because "n" is null at org.xmlunit.diff.NodeFilters$1.test(NodeFilters.java:33)

Root cause analysis

  • IterableNodeList with underlying NodeListIterator is used as collection of nodes in compareNodes method
  • NodeListIterator refers to NodeList's getLength() and item(int index) methods
  • in default Xerces DOM implementation for attribute node the AttrImpl.getLength() and AttrImpl.item(0) methods are called
  • AttrImpl.item(int index) has a condition resulting in null
    if (index != 0 || value == null) {
        return null;
    }
    
  • null is later passed to NodeFilters.Default predicate and fails on n.getNodeType()

Expected behavior

Attributes with null values could be treated as having empty values ("") and considered equal.
The javax.xml.transform API already serializes them as empty strings.

Proposed fix

Adding a null check in the NodeFilters.Default predicate, however i am not sure whether the null check would be safe considering the predicate applies to other node types as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions