Details
Description
The NodeComparator.compare() method has two faults when taken from the perspective where a predicate function returns multiple Attribute ( or Namespace) siblings.
The first issue is that compare(Object o1,Object o2) should return 0 when o1 == o2. This should be default behaviour as during the sorting process it is technically legal for the comparator to be called that way.
The bigger issue is that if o1 and o2 are both siblings, and both either Attributes, or Namespaces, then the code 'falls through', and uses the compare() result of the parent (Element) to test for the document order.
Unfortunately, they have the same parent (and the same depth), and, as a result, they always compare() as value 1. This always puts the o1 sibling after the o2 sibling.
Further, this breaks the Comparator 'contract', because:
1 == compare(SiblingA, SiblingB)
also:
1 == compare(SiblingB, SiblingA)
Attached are two files, the first is a test case showing the problem.
The second is a NodeComparator .java class with two changes to the current version in subversion:
1. it immediately returns 0 for o1 == o2
2. it does a special sibling-compare for sibling Attributes/Namespaces
The motivation for '2' is that the XPath specification does allow a preceding/following axis for namespaces/attributes (likely because DOM has no Attribute order assumption), but, almost all implementations have a 'natural' order for Attributes and Namespaces, and the axis-order must be consistent for any evaluation anyways.
This change provides consistency and reliability in the NodeComparator class.