我正在尝试编写一个应用程序的自动测试,它基本上将自定义消息格式转换为XML消息并将其发送到另一端 . 我有一组很好的输入/输出消息对,所以我需要做的就是发送输入消息并监听XML消息从另一端出来 .
当需要将实际输出与预期输出进行比较时,我遇到了一些问题 . 我的第一个想法就是对预期和实际消息进行字符串比较 . 这样做效果不好,因为我们拥有的示例数据并不总是一致地格式化,并且通常会有不同的别名用于XML命名空间(有时根本不使用命名空间 . )
我知道我可以解析两个字符串,然后遍历每个元素并自己进行比较,这不会太困难,但我觉得有一个更好的方法或我可以利用的库 .
所以,归结起来,问题是:
给定两个包含有效XML的Java字符串,您将如何确定它们在语义上是否等效?如果您有办法确定差异是什么,可以获得奖励积分 .
14 回答
听起来像XMLUnit的工作
http://www.xmlunit.org/
https://github.com/xmlunit
例:
以下将使用标准JDK库检查文档是否相同 .
normalize()是为了确保没有循环(技术上不会有任何循环)
上面的代码将要求空格中的空格相同,因为它保留并评估它 . Java附带的标准XML解析器不允许您设置功能以提供规范版本或了解
xml:space
如果这将成为问题,那么您可能需要替换XML解析器(如xerces)或使用JDOM .Xom有一个Canonicalizer实用程序,可以将您的DOM转换为常规形式,然后您可以进行字符串化和比较 . 因此,无论空白不规则或属性排序如何,您都可以对文档进行定期,可预测的比较 .
这在具有专用可视字符串比较器(如Eclipse)的IDE中尤其有效 . 您可以直观地表示文档之间的语义差异 .
最新版本的XMLUnit可以帮助断言两个XML的工作是相同的 . 此案件可能还需要
XMLUnit.setIgnoreWhitespace()
和XMLUnit.setIgnoreAttributeOrder()
.请参阅下面的XML单元使用的简单示例的工作代码 .
如果使用Maven,请将其添加到
pom.xml
:既然你说“语义等价”我认为你的意思是你想做的不仅仅是字面上验证xml输出是(字符串)等于,你想要的东西像
<foo>这里的一些东西</ foo> </ code>
和
<foo>这里的一些东西</ foo> </ code>
读作同等的 . 最终,你要在重构消息的任何对象上定义“语义等价”是至关重要的 . 只需从消息中构建该对象,并使用自定义equals()来定义您要查找的内容 .
谢谢,我扩展了这个,试试这个......
在Tom 's answer, here'上构建使用XMLUnit v2的示例 .
它使用这些maven依赖项
..这是测试代码
概述这个的文档是https://github.com/xmlunit/xmlunit#comparing-two-documents
斯卡弗曼似乎给出了一个很好的答案 .
另一种方法可能是使用xmlstarlet(http://xmlstar.sourceforge.net/)等命令行实用程序格式化XML,然后格式化两个字符串,然后使用任何diff实用程序(库)来区分生成的输出文件 . 当问题与名称空间有关时,我不知道这是否是一个很好的解决方案 .
我正在使用Altova DiffDog,它可以选择在结构上比较XML文件(忽略字符串数据) .
这意味着(如果选中'忽略文本'选项):
和
在结构平等的意义上是平等的 . 如果您有不同数据但不是结构的示例文件,这很方便!
这将比较完整的字符串XML(在途中重新格式化它们) . 它使您可以轻松使用IDE(IntelliJ,Eclipse),因为您只需单击并直观地查看XML文件中的差异 .
我更喜欢这个XmlUnit,因为客户端代码(测试代码)更干净 .
AssertJ 1.4具有比较XML内容的特定断言:
这是Documentation
下面的代码适合我
将JExamXML与java应用程序一起使用
我需要与主要问题中请求的功能相同的功能 . 由于我不被允许使用任何第三方库,我已经基于@Archimedes Trajano解决方案创建了我自己的解决方案 .
以下是我的解决方案 .
它比较两个XML字符串,并通过将它们转换为两个输入字符串中的唯一值来处理任何不匹配的命名空间映射 .
可以微调,即名称空间的翻译案例 . 但是根据我的要求,只做这项工作 .