#317 A null Element attribute is counted as an attribute

closed-fixed
nobody
5
2010-02-06
2009-07-01
Ernst de Haan
No

When setting an Element attribute to null, somehow the attribute is still counted as an attribute, it is returned from the attribute map (with value null) and it causes two otherwise equal elements to be considered not equal.

Here's a test case:

public void testElementEquals() throws Exception {
assertFalse(new Element("Test").equals(new Object()));
assertFalse(new Element("Test").equals("" ));
assertFalse(new Element("Test").equals(null ));

assertEquals(new Element("Test"), new Element("Test"));

Element elem1 = new Element("Test");
elem1.setAttribute("a", "0");
elem1.setAttribute("b", "1");
elem1.setAttribute("c", "2");

Element elem2 = new Element("Test");
elem2.setAttribute("c", "2");
elem2.setAttribute("b", "1");
elem2.setAttribute("a", "0");

assertTrue(elem1.equals(elem1));
assertTrue(elem1.equals(elem2));
assertTrue(elem2.equals(elem1));
assertTrue(elem2.equals(elem2));

elem1.addChild(new Element("Test2"));
assertFalse(elem1.equals(elem2));
assertFalse(elem2.equals(elem1));
elem2.addChild(new Element("Test2"));
assertTrue(elem1.equals(elem2));
assertTrue(elem2.equals(elem1));

elem1.addText("Bla");
assertFalse(elem1.equals(elem2));
assertFalse(elem2.equals(elem1));
elem2.addText("Bla");
assertTrue(elem1.equals(elem2));
assertTrue(elem2.equals(elem1));

elem1.addChild(new Element("Test3"));
assertFalse(elem1.equals(elem2));
assertFalse(elem2.equals(elem1));
elem2.addChild(new Element("Test3"));
assertTrue(elem1.equals(elem2));
assertTrue(elem2.equals(elem1));

elem2.setAttribute("a899", null);
assertTrue(elem1.equals(elem2));
assertTrue(elem2.equals(elem1));
}

The last two lines fail. I propose adding this test case to ElementTests.java.

The real issue is probably in the ChainedMap.

Discussion

  • What behaviour do you think it should have?
    - Ignore (if (value==null) return;)
    - Fail with an IAE
    - Add an empty string
    - Remove the attribute

     
  • Ernst de Haan
    Ernst de Haan
    2010-02-06

    What I would expect that if an attribute value is set to null, then the attribute is treated as being unset from that point on.

     
  • Ernst de Haan
    Ernst de Haan
    2010-02-06

    See: http://github.com/znerd/xins/blob/master/src/java/org/xins/common/xml/Element.java

    I think the issue is fixed there in the setAttribute(String,String,String,String) method, as follows:

    public void setAttribute(String namespacePrefix, String namespaceURI, String localName, String value)
    throws IllegalArgumentException {

    // Construct a QualifiedName object; this will check the preconditions
    QualifiedName qn = new QualifiedName(namespacePrefix, namespaceURI, localName);

    // If there are no attributes and the attribute should become null, then
    // nothing needs to be done
    if (_attributes == null && value == null) {
    return;

    // Check if there are any attributes yet, since the collection is lazily
    // initialized
    } else if (_attributes == null) {
    _attributes = new LinkedHashMap<QualifiedName,String>();
    }

    // Reset or set the attribute
    if (value == null) {
    _attributes.remove(qn);
    } else {
    _attributes.put(qn, value);
    }
    }

     
    • status: open --> closed-fixed
     
  • Fixed, will be in 2.3-alpah3.