Doc4j:比较两个文件失败,因为不同的元素类型

问题描述:

我试着写一些JUnit测试的Docx4J发生器我已经写。 我想我发生器的输出节点与我想从字符串加载预期节点进行比较。Doc4j:比较两个文件失败,因为不同的元素类型

所以,我创建了我的“实际”节点(发电机输出),像这样:

Node xmlNodeActual = XmlUtils.marshaltoW3CDomDocument(actual).getDocumentElement(); 

其中,“实际”是由我的发电机创建的对象。

对于我的“预期”节点,我写了下面的代码:

Document doc = docBuilder.parse(new InputSource(new ByteArrayInputStream(strXmlNode.getBytes("utf-8")))): 
Node xmlNodeExpected = doc.getDocumentElement(); 

strXmlNode是抱着期望的XML字符串。 虽然我的两个节点都是平等的,据我可以从视觉差异来讲,调用下面的产量“假”的结果:

xmlNodeActual.isEqualNode(xmlNodeExpected) 

我怀疑的原因是运行时类型的两个节点的不同:

  • xmlNodeActual:org.apache.xerces.dom.DeferredElementImpl
  • xmlNodeExpected:org.apache.xerces.dom.ElementNSImpl

我喜欢我的测试设计,因为它可以让我为大型生成器快速编写大量测试用例。但是,我没有看到将这种方法与“isEqualNode”结合使用的方法。 我必须写我自己的比较器或者是有办法,我不知道,以确保类型节点都是一样的吗?用这样的方法

注意@迈克尔凯和@JasonPlutext贡献有趣和更好的选择上一般情况下如何测试XML输出,您可能需要考虑。

至于我的具体问题和问题,即比较两个XML节点与“isEqualNode”,一个源于输入字符串,一个源于数据转换,我不得不做下列事情:而不是解析字符串,我可以通过InputStream解组,从而获得所需的节点类型。

// creating the "actual" node I want to test (nothing changed here) 
Node xmlNodeActual = XmlUtils.marshaltoW3CDomDocument(actual).getDocumentElement(); 

//... 

// Instead of parsing the string, just unmarshal and marshal it once 
Object expected = XmlUtils.unmarshal(new ByteArrayInputStream(strXmlNode.getBytes("utf-8"))); 
Node xmlNodeExpected = XmlUtils.marshaltoW3CDomDocument(expected).getDocumentElement(); 
if(!xmlNodeActual.isEqualNode(xmlNodeExpected)) { 
// ... 
} 

这产生了相同的节点类型,并按我的设置工作。尽管如此,比较两种XML树的方式有一些缺陷,正如Michael Kay所指出的那样,所以不要认为这是最佳做法,而是要求通用的XML比较的另一个答案。

的一个问题是,它只是给出了一个布尔答案,它不会告诉你什么是两个节点之间的实际差异。另一个问题是,你不能告诉它你认为什么差异是显着的:例如(据我所知)冗余名称空间声明被认为是重要的这种特定的方法。空白通常是有问题的。我不得不使用XPath深等于()方法同样的问题,并写下了saxon:deep-equal变异的结果。但我现在更愿意使用一组XPath断言来测试预期的结果。 W3C的XSLT测试套件使用与测试断言像这样的这种技术:

<result> 
    <all-of> 
     <assert>/root/p[1]/text()[1] = 'Tekst '</assert> 
     <assert>/root/p[1]/text()[2] = ' etc..'</assert> 
     <assert>/root/p[2]/text()[1] = 'Tekst '</assert> 
     <assert>/root/p[2]/text()[2] = ' etc..'</assert> 
    </all-of> 
    </result> 

我没有在同一时间有一个小工具,它会生成一个XML文档的断言这样的名单,但我现在倾向于做他们手动。最大的好处是,如果出现问题,诊断程序会告诉你哪个断言失败。

+0

感谢迈克尔,我意识到我的方法的局限性。但考虑到我正在工作的技术和非功能限制,这将是一个很好的妥协。我比较的节点很小,但很多。在我的设置中,冗余名称空间依赖项和空白都没有问题,但是感谢您指出它。我写过类似于saxon的东西:对于不同于XML的语言,深入等同于之前,但是我的问题与我的方法相比较少,如果有一种简单的方法来控制分析产生的节点类型。 –

+0

该规范没有提示基于第二个节点树的实现类允许比较失败,但当然在实现中可能存在一个错误。就我个人而言,我认为您忽略的两棵树之间存在较小的差异的可能性更大。可能值得下载Saxon并查看fn:deep-equal()(或者saxon:deep-equal())所说的内容。 –

+0

我想我在这里不同意: 请查看[doc](https://docs.oracle.com/javase/7/docs/api/org/w3c/dom/Node.html#isEqualNode)。 它读取: _两个节点是相等的当且仅当满足以下条件:_ _这两个节点是相同类型._ _..._ –

+0

嗨@JasonPlutext。感谢提示。那些,伴随着一个愉快的睡眠之夜,让我得到了我所寻找的实用解决方案(将尽快更新我的问题,并且现在我已经结束了)。一般来说,我认为xmlunit是正确的选择。 请注意:我的声望还不够高,无法显示我对此答案的满意度。 –