首先感谢你们这个精彩的图书馆,它非常棒。
我在xml文档中按不同顺序比较元素时遇到问题。我已经开发了一个自定义的ElementSelector与NodeMatcher(后面的代码)一起使用,但它似乎仍然基于元素顺序检查而不是元素内容。 我来写一个例子
控制
<Parent>
<Person>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Email>johndoe@email.com</Email>
</Person>
<Person>
<FirstName>Mickey</FirstName>
<LastName>Mouse</LastName>
<Email>mm@email.com</Email>
</Person>
<Person>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Email />
</Person>
</Parent>
测试
<Parent>
<Person>
<FirstName>Mickey</FirstName>
<LastName>Mouse</LastName>
<Email>mm@email.com</Email>
</Person>
<Person>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Email>johndoe@email.com</Email>
</Person>
<Person>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Email />
</Person>
</Parent>
我如何制作差异
Diff diff = DiffBuilder.compare(refSource)
.withTest(testSource)
.checkForSimilar()
.ignoreWhitespace()
.normalizeWhitespace()
.withNodeMatcher(new DefaultNodeMatcher(selector))
.build();
我是如何创建ElementSelector选择器的
ElementSelector selector = ElementSelectors.conditionalBuilder()
.whenElementIsNamed("Person").thenUse(new PersonNodeMatcher())
.defaultTo(ElementSelectors.byNameAndText).build();
如何实际实现PersonNodeMatcher
public class PersonNodeMatcher extends BaseElementSelector {
@Override
protected boolean canBeCompared(Element control, Element test) {
String controlFirstName = control.getElementsByTagName("FirstName").item(0).getTextContent();
String controlLastName = control.getElementsByTagName("LastName").item(0).getTextContent();
Node controlEmailNode = control.getElementsByTagName("Email").item(0);
String controlEmail = null;
if ( controlEmailNode != null) {
controlEmail = controlEmailNode.getTextContent();
}
String testFirstName = test.getElementsByTagName("FirstName").item(0).getTextContent();
String testLastName = test.getElementsByTagName("LastName").item(0).getTextContent();
Node testEmailNode = test.getElementsByTagName("Email").item(0);
String testEmail = null;
if (testEmailNode != null) {
testEmail = testEmailNode.getTextContent();
}
return bothNullOrEqual(controlFirstName,testFirstName) &&
bothNullOrEqual(controlLastName,testLastName) &&
bothNullOrEqual(controlEmail,testEmail);
}
例程仍在按顺序检查节点,因此它们永远不会匹配。 我认为提供节点自定义节点匹配器我将能够使用提供的tagName检查所有元素。
我做错了什么或根本不可能?
[UPDATE] 使用alpha3我必须对代码进行一些修改,特别是:
ElementSelector selector = ElementSelectors.conditionalBuilder()
.whenElementIsNamed("Person").thenUse(new PersonNodeMatcher()).build();
Diff diff = DiffBuilder.compare(refSource)
.withTest(testSource)
.checkForSimilar()
.ignoreWhitespace()
.normalizeWhitespace()
.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.or(selector,ElementSelectors.Default)))
.build();
答案 0 :(得分:0)
我没有使用ElementSelectors.or
内的DefaultNodeMatcher
,而是使用了varargs
构造函数
Diff diff = DiffBuilder.compare(refSource)
.withTest(testSource)
.checkForSimilar()
.ignoreWhitespace()
.normalizeWhitespace()
.withNodeMatcher(
new DefaultNodeMatcher(
selector,ElementSelectors.Default)
)
.build();
解释了这两种方法之间的差异here。
这解决了我的主要问题,因为DifferenceEvaluator
输出的文档不同,因为this(查看段落的末尾),所以仍然存在问题。实际上,文档是SIMILAR
而不是IDENTICAL
,因为内部元素的顺序不相等。为了阻止DifferenceEvaluator
的此类输出,目前我已使用特定DiffBuilder
DifferenceEvaluator
.withDifferenceEvaluator(((comparison, outcome) -> {
if (outcome == ComparisonResult.DIFFERENT &&
comparison.getType() == ComparisonType.CHILD_NODELIST_SEQUENCE) {
return ComparisonResult.EQUAL;
}
return outcome;
}))
即使Stefan Bodewig建议的最佳解决方案可能是chain
我的DifferenceListeners.Default
实施,也不会检查结果。