Java XML单元-在不同的XML元素上使用自定义元素选择器

Java XML单元-在不同的XML元素上使用自定义元素选择器,java,xml,diff,xmlunit,xmlunit-2,Java,Xml,Diff,Xmlunit,Xmlunit 2,将xml文档中的各种元素与XMLUnit(2.2.1)进行比较时遇到问题。在我的文档中有几个xml元素,我想 知道他们是否彼此不同。但是,我不想以相同的方式比较所有xml元素。有时我只想通过名字来比较它们,而在其他情况下,我想通过名字和属性或者名字和文本来比较它们 下面是一个示例(请参见注释) 控制 <?xml version="1.0" encoding="UTF-8"?> <ROOT> <LANGUAGES> <!-- Compar

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

下面是一个示例(请参见注释)

控制

<?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>
测试:

我尝试将ElementSelectors与ElementSelectors.conditionalBuilder()结合使用,以仅在特定元素上应用ElementSelector(当ElementInsnabled时)。也许这不是我想要达到的目标的正确方法

这是我用于测试的代码:

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-130000-3)已被删除(未替换),名字已更改

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


谢谢你的帮助

DefaultNodeMatcher
的构造函数中使用三个
ElementSelector
s与在多个条件下使用单个
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)
应为子节点列表长度“4”,但为“2”-将at/ROOT[1]/LANGUAGES[1]与at/ROOT[1]/LANGUAGES[1]进行比较(不同)
应为子级“LANGUAGE”,但为“null”-在/ROOT[1]/LANGUAGES[1]/LANGUAGE[2]处与(不同)进行比较
应为子级“LANGUAGE”,但为“null”-在/ROOT[1]/LANGUAGES[1]/LANGUAGE[3]处与(不同)进行比较
应为子节点列表长度“4”,但为“2”-正在将at/ROOT[1]/code[1]与at/ROOT[1]/code[1]进行比较(不同)
应为子项“CODE”,但为“null”-在/ROOT[1]/CODE[1]/CODE[1]处与(不同)进行比较
应为子项“CODE”,但为“null”-在/ROOT[1]/CODE[1]/CODE[3]处与(不同)进行比较
预期文本值“Max”,但为“Tim”-比较/ROOT[1]/CONTACT[1]/FIRSTNAME[1]/text()[1]处的Max与/ROOT[1]/CONTACT[1]/FIRSTNAME[1]/text()[1]处的Tim(不同)
下面是发生的情况:当XMLUnit使用
值查看
语言
时,您构建的第一个条件
元素选择器将为所有候选
语言
元素返回
false

使用multi-arg
DefaultNodeMatcher
构造函数时,将询问下一个
ElementSelector
,在您的情况下,它也将返回
false
,因为它只对
code
元素感兴趣。然后咨询第三个
ElementSelector
,它将愉快地接受任何名为
LANGUAGE
的测试元素

当使用我在上面设置的单个
元素选择器时,只要
谓词返回
true
,组合选择器将永远不会参考任何备选方案。这意味着一旦选择器返回了
false
,就不会再想
语言
元素了


我将尝试更新您的示例,并希望您能帮助我改进文档。

谢谢Stefan,这正是我想要的:)!我读了几遍你的解释后补充说,我想我现在明白了。在过去的几天里,维基页面实际上对我非常有用。太好了,你更新了。多特蒙德的问候
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)