【问题标题】:XML Unit - Using custom element selectors on different xml elementsXML 单元 - 在不同的 xml 元素上使用自定义元素选择器
【发布时间】:2017-10-02 11:33:45
【问题描述】:

我在将 xml 文档中的各种元素与 XMLUnit (2.2.1) 进行比较时遇到问题。在我的文档中有几个 xml 元素,我想 知道,它们是否彼此不同。但是,我不想以相同的方式比较所有 xml 元素。有时我只是想通过他们的名字来比较它们。在其他情况下我想通过名字和属性或名字和文本来比较它们。

这是一个例子(见 cmets)

控制

<?xml version="1.0" encoding="UTF-8"?>
<ROOT>
   <LANGUAGES>
      <!-- Compare LANGUAGE by Name and Attribute -->
      <LANGUAGE VALUE="DE" />
      <LANGUAGE VALUE="EN" />
      <LANGUAGE VALUE="IT" />
      <LANGUAGE VALUE="FR" />
   </LANGUAGES>
   <CODES>
      <!-- Compare CODE by Name and Text -->
      <CODE>10000-1</CODE>
      <CODE>20000-2</CODE>
      <CODE>30000-3</CODE>
      <CODE>40000-4</CODE>
   </CODES>
   <CONTACT> <!-- Compare CONTACT and Children just by Name -->
      <FIRSTNAME>Max</FIRSTNAME>
      <SURNAME>Mustermann</SURNAME>
   </CONTACT>
</ROOT>

测试:

<?xml version="1.0" encoding="UTF-8"?>
<ROOT>
   <LANGUAGES>
      <!-- Compare LANGUAGE by Name and Attribute -->
      <LANGUAGE VALUE="DE" />
      <LANGUAGE VALUE="FR" />
   </LANGUAGES>
   <CODES>
      <!-- Compare CODE by Name and Text -->
      <CODE>20000-2</CODE>
      <CODE>40000-4</CODE>
   </CODES>
   <CONTACT> <!-- Compare CONTACT and Children by Name -->
      <FIRSTNAME>Tim</FIRSTNAME>
      <SURNAME>Mustermann</SURNAME>
   </CONTACT>
</ROOT>

我尝试将 ElementSelectors 与 ElementSelectors.conditionalBuilder (https://github.com/xmlunit/user-guide/wiki/SelectingNodes#conditional-elementselectors) 结合使用,以仅在特定元素上应用 ElementSelector (whenElementIsNamed)。也许这不是我想要实现的正确方法。

这是我用于测试的代码:

public void xmlDiff() {
    String control = getControlDocument(); //
    String test = getTestDocument(); //
    Diff myDiff = DiffBuilder.compare(control)//
            .withTest(test) //
            .ignoreWhitespace() //
            .ignoreComments() //
            .checkForSimilar() //
            .withNodeMatcher(new DefaultNodeMatcher(partialElementSelector("LANGUAGE", ElementSelectors.byNameAndAllAttributes), partialElementSelector("CODE",ElementSelectors.byNameAndText), ElementSelectors.byName)) //
            .build();
    assertThat(myDiff.hasDifferences()).isTrue(); // 
}

    private ElementSelector partialElementSelector(final String expectedName, final ElementSelector elementSelector) {
        return ElementSelectors.conditionalBuilder().whenElementIsNamed(expectedName).thenUse(elementSelector).build();
    }

我真正需要的是信息,两个语言(EN,IT)和两个代码(10000-1,30000-3)已被删除(未替换)并更改了FIRSTNAME。

无论是否使用 XML 单元 (DiffBuilder),我如何获取这些信息?

感谢您的帮助!

【问题讨论】:

    标签: java xml diff xmlunit xmlunit-2


    【解决方案1】:

    DefaultNodeMatcher 的构造函数中使用三个ElementSelector 与在多个条件下使用单个ElementSelector 之间存在细微差别。

    你想用三个选择器实现的也可以写成

    ElementSelectors.conditionalBuilder()
        .whenElementIsNamed("LANGUAGE")
        .thenUse(ElementSelectors.byNameAndAllAttributes)
        .whenElementIsNamed("CODE")
        .thenUse(ElementSelectors.byNameAndText)
        .elseUse(ElementSelectors.byName)
        .build();
    

    乍一看,这似乎是一样的,但事实并非如此。事实上它会起作用。这是我从你的例子中得到的:

    Expected child nodelist length '4' but was '2' - comparing <LANGUAGES...> at /ROOT[1]/LANGUAGES[1] to <LANGUAGES...> at /ROOT[1]/LANGUAGES[1] (DIFFERENT)
    Expected child 'LANGUAGE' but was 'null' - comparing <LANGUAGE...> at /ROOT[1]/LANGUAGES[1]/LANGUAGE[2] to <NULL> (DIFFERENT)
    Expected child 'LANGUAGE' but was 'null' - comparing <LANGUAGE...> at /ROOT[1]/LANGUAGES[1]/LANGUAGE[3] to <NULL> (DIFFERENT)
    Expected child nodelist length '4' but was '2' - comparing <CODES...> at /ROOT[1]/CODES[1] to <CODES...> at /ROOT[1]/CODES[1] (DIFFERENT)
    Expected child 'CODE' but was 'null' - comparing <CODE...> at /ROOT[1]/CODES[1]/CODE[1] to <NULL> (DIFFERENT)
    Expected child 'CODE' but was 'null' - comparing <CODE...> at /ROOT[1]/CODES[1]/CODE[3] to <NULL> (DIFFERENT)
    Expected text value 'Max' but was 'Tim' - comparing <FIRSTNAME ...>Max</FIRSTNAME> at /ROOT[1]/CONTACT[1]/FIRSTNAME[1]/text()[1] to <FIRSTNAME ...>Tim</FIRSTNAME> at /ROOT[1]/CONTACT[1]/FIRSTNAME[1]/text()[1] (DIFFERENT)
    

    所以会发生这样的事情:当 XMLUnit 查看 LANGUAGEVALUE en 时,您构建的第一个条件 ElementSelector 将为所有候选 LANGUAGE 元素返回 false

    当使用多参数 DefaultNodeMatcher 构造函数时,将询问下一个 ElementSelector - 在您的情况下,它也将返回 false,因为它只对 CODE 元素感兴趣。然后咨询第三个ElementSelector,它将很乐意接受任何名为LANGUAGE 的测试元素。

    当使用我在上面设置的单个ElementSelector 时,一旦Predicate 返回true,组合选择器将永远不会咨询任何替代方案。这意味着一旦选择器返回 false,就不会再考虑 LANGUAGE 元素。

    我将尝试使用您的示例更新 https://github.com/xmlunit/user-guide/wiki/SelectingNodes#nodematcher,并希望在改进文档方面获得您的帮助。

    【讨论】:

    • 谢谢 Stefan,这就是我要找的 :)!
    • 读了几次你的解释后,我想我现在明白了。在过去的几天里,wiki 页面实际上对我非常有用。太好了,你更新了它。来自多特蒙德的问候
    猜你喜欢
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多