XMLUnit 2.0 - 无法避免与自定义元素选择器进行顺序比较

时间:2016-01-22 12:02:53

标签: java xml xmlunit-2

首先感谢你们这个精彩的图书馆,它非常棒。

我在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();

1 个答案:

答案 0 :(得分:0)

  1. 我搬到了最新的alpha-alpha-03。 alpha-02存在问题;
  2. 我没有使用ElementSelectors.or内的DefaultNodeMatcher,而是使用了varargs构造函数

    Diff diff = DiffBuilder.compare(refSource)
                           .withTest(testSource)
                           .checkForSimilar()
                           .ignoreWhitespace()
                           .normalizeWhitespace()
                           .withNodeMatcher(
                                 new DefaultNodeMatcher(
                                        selector,ElementSelectors.Default)
                           )
                           .build();
    

    解释了这两种方法之间的差异here

  3. 这解决了我的主要问题,因为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实施,也不会检查结果。