From: Stefan B. <bo...@ap...> - 2015-02-10 13:58:38
|
Hi all the concept of ElementQualifier in XMLUnit 1.x and its cousin ElementSelector in 2.x seems to be difficult. Almost all questions I've answered in the past years and many of the issues I closed have been related to not understanding the concept or chosing the wrong ElementQualifier - usually RecursiveElementNameAndTextQualifier. We need to explain it better, which is part of what we need to do in the new user guide, but we also need to make it easier to customize the selection process. I've started to implement "combinators" for ElementSelectors based on ideas Bastain Blankenburg expressed as feature requests about - what? - five years ago. So you can now do something like import static org.xmlunit.diff.ElementSelectors.*; ElementSelector es = or(selectorForElementNamed("foo", byNameAndText), selectorForElementNamed("bar", byNameAndAttributes("id")), byName); in order to pick foos based on their nested text, bars based on an attribute and solely rely on the name by default. This is a big step forward and I can also see some nice builder syntax forming ElementSelector es = Builder .whenElementIsNamed("foo").thenUse(byNameAndText) .whenElementIsNamed("bar").thenUse(byNameAndAttributes("id")) .otherwise(byName) .build(); To get rid of RecursiveElementNameAndTextQualifier this is not enough, back then Bastian suggested a child element qualifier, which would be a combinator that picked a child node and applied a different selector. This falls short for recursion. I've been thinking about generalizing the idea of child nodes to XPath expressions using the current element as context. Taking http://stackoverflow.com/questions/23752354/xmlunit-recursiveelementnameandtextqualifier-not-working as example one could use something like byXPath(".//a", byNameAndText) and apply that to "td" and "tr" elements. The corresponding selector would run the Nodes returned by evaluating the XPath through a comparison process and match the elements if all nodes returned could be matched. But I'm not sure this really is easy enough to understand and I'm afraid it would become repetitive. So a better idea is more than welcome. Also ElementSelector only receives Elements as context, therefore the big brother of selectorForElementNamed - conditionalSelector - works with a Predicate<Element> to see whether it should apply. This may be cumbersome and I can easily see problems where the element name is not enough and I need to know where the element is, something like the XPathContext would be helpful. This might require a change to the ElementSelector and likely the NodeMatcher APIs. Any ideas? Stefan |