2

まず、この素晴らしいライブラリに感謝します。本当に素晴らしいです。

XML ドキュメント内で要素を異なる順序で比較する際に問題が発生しています。NodeMatcher (後のコード) で使用するカスタム ElementSelector を開発しましたが、要素の内容よりも要素の順序に基づいてチェックしているようです。例を書いてみましょう

コントロール

<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ですべての要素をチェックできると思いました。

私は何か間違ったことをしていますか、それとも単に不可能ですか?

[更新] 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();
4

1 に答える 1

1
  1. 私は最新のアルファである 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();
    

    2 つのアプローチの違いについては、こちらで説明しています。

  3. DifferenceEvaluatorこれは私の主な問題を解決しましたが、これが原因でそのドキュメントが異なって出力されていたため、まだ問題がありました段落の最後を見てください)。実際、内部要素の順序が等しくないため、文書は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あり、結果のチェックを削除することです。

于 2016-01-25T10:12:14.343 に答える