Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java xmlunit:ElementSelectors.conditionalBuilder出错_Java_Xml_Xmlunit_Xmlunit 2 - Fatal编程技术网

Java xmlunit:ElementSelectors.conditionalBuilder出错

Java xmlunit:ElementSelectors.conditionalBuilder出错,java,xml,xmlunit,xmlunit-2,Java,Xml,Xmlunit,Xmlunit 2,因此,我有以下输入、预期输出和实际输出xml: input.xml 当我运行上述输入并与expected-output.xml进行比较时,我得到了以下差异: [期望的子对象]{http://test.org/standards/intake}RqUID'但为'null'-将/ProductRq[1]/SvcRq[1]/NotificationRq[1]/RqUID[1]与(不同)进行比较,应为子项'null',但为'{http://test.org/standards/intake}RqUID'

因此,我有以下输入、预期输出和实际输出xml:

input.xml

当我运行上述输入并与expected-output.xml进行比较时,我得到了以下差异:

[期望的子对象]{http://test.org/standards/intake}RqUID'但为'null'-将/ProductRq[1]/SvcRq[1]/NotificationRq[1]/RqUID[1]与(不同)进行比较,应为子项'null',但为'{http://test.org/standards/intake}RqUID'-与at/ProductRq[1]/SvcRq[1]/NotificationRq[1]/RqUID[1](不同)相比

我不明白为什么我的元素选择器不能工作,我是否使用错误?我的目标是,每当找到TransmissionId或NotificationRq/RqUID时,只通过名称将它们与预期的输出版本相匹配,否则对其他元素使用名称和文本,因为这些元素包含唯一生成的ID,这些ID会更改每个测试运行,并且无法预测(为了以后创建更复杂的选择器,例如,在名称空间添加到名称和属性时通过名称和属性比较ProductRq)。我是否缺少一些东西,我是否能够将两个XPath选择器组合在一起,而不是将几个when/then行和默认情况组合在一起


注意:xml是通过xslt转换的。PRoductRq上的名称空间不在源文档中;源文件被复制,名称空间被添加到PRoductRq中,然后与一些元素删除/修改/添加一起发送以供输出。

XMLUnit表示
通知RQ
中的
RqUID
元素与当然他们是不同的

.whenElementIsNamed("NotificationRq")
.thenUse(ElementSelectors.byXPath("./RqUID", ElementSelectors.byName))
意思是:当XMLUnit试图为
NotificationRq
元素查找合作伙伴时,它必须搜索具有
RqUID
子元素的
NotificationRq
,并且只使用
RqUID
元素

它不为任何其他元素设置任何规则,特别是
RqUID
本身。对于
RqUID
元素,默认规则适用,并且

.elseUse(ElementSelectors.byNameAndText)
表示:如果两个元素的名称和嵌套的文本匹配,XMLUnit只接受两个元素作为成对元素。这与所讨论的
RqUID
元素不同

您的整个
元素选择器
显示

  • 匹配
    Audit
    s,如果它们具有任意内容的
    TransID
    子级
  • 匹配
    NotificationRq
    s,如果它们具有任意内容的
    RqUID
  • 否则,请使用元素名称和嵌套文本
这不符合您的示例。查看您可能想要的XML

  • 通过元素名和嵌套文本匹配几乎所有内容(尽管从示例中可以看出,元素名就足够了)
  • 忽略
    TransId
    的子级
    Audit
    s的嵌套文本
  • 忽略
    NotificationRq
“element named
foo
没有内置谓词。如果它是名为
bar
的元素的子元素,则可能类似于

Predicate<Element> transIdInAudit = e -> {
     if (e == null || e.getParentNode() == null) {
         return false;
     }
     return "TransID".equals(e.getLocalName()) && "Audit".equals(e.getParentNode().getLocalName());
};
如果它们有匹配的
RqUID
,可能您真的想匹配
SvcRq
,可能不想。如果是这样,您会使用当前用于
通知rq
的结构

这本身不足以忽略匹配的
TransId
RqUID
元素的嵌套文本,它只会确保XMLUnit选择您希望它使用的节点。对于嵌套文本,您需要一个
DifferenceEvaluator

假设您使用的是
元素选择器。默认情况下,ByName和Text
对于所有匹配的节点,嵌套的文本都是相同的,除了要忽略内容的两个特定元素。因此
DifferenceEvaluator
类似于

DifferenceEvaluators.chain(DifferenceEvaluators.Default,
    DifferenceEvaluators.downgradeDifferencesToEqual(ComparisonType.TEXT_VALUE))

应该可以工作。

很好的解释,我想我误解了byXPath元素选择器,我认为这是按照这样的思路:如果元素名为this,那么将这个子元素与提供的选择器匹配,而不是它必须只使用带有默认规则的RqUID。我最终实现了2 DifferenceEvaluator,找到了一个解决方案但是这更干净
.whenElementIsNamed("NotificationRq")
.thenUse(ElementSelectors.byXPath("./RqUID", ElementSelectors.byName))
.elseUse(ElementSelectors.byNameAndText)
Predicate<Element> transIdInAudit = e -> {
     if (e == null || e.getParentNode() == null) {
         return false;
     }
     return "TransID".equals(e.getLocalName()) && "Audit".equals(e.getParentNode().getLocalName());
};
.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.conditionalBuilder()
    .when(transIdInAudit)
    .thenUse(ElementSelectors.byName)
    .when(rqUIDInNotificationRq) // similar to transIdInAudit
    .thenUse(ElementSelectors.byName)
    .elseUse(ElementSelectors.byNameAndText)
    .build())
DifferenceEvaluators.chain(DifferenceEvaluators.Default,
    DifferenceEvaluators.downgradeDifferencesToEqual(ComparisonType.TEXT_VALUE))