之前都使用XmlUnit来对比xml字符串,今天发现当出现如下需求时,XMLUNIT无法满足或者说有bug,特自己写了对比方法。
需求:需要对比如下xml字符串,要求不对比其中的sign和time字段,其他字段都需要对比。
<?xml version="1.0" encoding="utf-8"?>
<SlotPermResult-array>
<SlotPermResult>
<appId>elbert_app_dsc007</appId>
<slotIds>elb_wsi_001</slotIds>
<time>1236586307734</time>
<sign>822a379aec82755afaa9c63eea3b05b9</sign>
<errorCode></errorCode>
<errorMessage></errorMessage>
</SlotPermResult>
<SlotPermResult>
<appId>elbert_apx_dsc008</appId>
<slotIds></slotIds>
<time>1236586307734</time>
<sign>7ce9e326cb28b0084f7f331dcbb79f50</sign>
<errorCode></errorCode>
<errorMessage></errorMessage>
</SlotPermResult>
<SlotPermResult>
<appId>elbert_app_dsc008</appId>
<slotIds>elb_wsi_002</slotIds>
<time>1236586307734</time>
<sign>2ea135b978c75fb639fe65909283dcba</sign>
<errorCode></errorCode>
<errorMessage></errorMessage>
</SlotPermResult>
</SlotPermResult-array>
尝试使用XmlUnit的方法
XMLAssert.assertXpathValuesEqual(path7,ExpXmlText,path7,ActXmlText);
结果发现只对第一个SlotPermResult节点的内容(子节点进行对比),不符合我们的需求。
原因XMLAssert根据Path找节点,只找第一个节点。所以只好自己写代码。
关键函数,需要根据Path找到符合这一路径的所有节点源码如下
public static NodeList selectNodes(String express, String xmlStr) throws Exception
{//查找节点,返回符合条件的节点集。
DocumentBuilder builder = factory.newDocumentBuilder();
InputStream is = String2InputStream(xmlStr);
org.w3c.dom.Document doc = builder.parse(is);
org.w3c.dom.Element root = doc.getDocumentElement();
NodeList result = null;
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
try {
result = (NodeList) xpath.evaluate(express, root,
XPathConstants.NODESET);
} catch (XPathExpressionException e) {
e.printStackTrace();
}
return result;
}
辅助函数:由于我们要传入的都是XML字符串,所以在这之前需要把字符串转成Stream
源码如下
static InputStream String2InputStream(String str) throws Exception{
ByteArrayInputStream stream = new ByteArrayInputStream(str.getBytes("utf-8"));
return stream;
}
搞定之后,我们需要对所有需要对比的路径都放在List参数中传给对比函数,让对比函数逐一进行对比
对比函数源码如下
@SuppressWarnings("unchecked")
public static void assertEqualsNodes(String ExpXml,String ActXml,List list) throws Exception
{
for(int i =0; i < list.size(); i++)
{
String path = list.get(i).toString();
NodeList nlExp = XmlStringUtil.selectNodes(path, ExpXml);
NodeList nlAct = XmlStringUtil.selectNodes(path, ActXml);
Assert.assertEquals(path+"路径下的节点数目不相同:",nlExp.getLength(),nlAct.getLength());
for(int j=0 ; j< nlExp.getLength(); j++)
{
Assert.assertEquals(path+"路径下第"+j+"个节点内容:",nlExp.item(j).getTextContent(),nlAct.item(j).getTextContent());
}
//Assert.assertEquals(nlExp,nlAct);
}
}
调用时候的代码片段如下:
String ExpXmlText = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ "<SlotPermResult-array> " + "<SlotPermResult> "
+ "<appId>elbert_app_dsc007</appId> "
+ "<slotIds>elb_wsi_001</slotIds> "
+ "<time>1236586307734</time> "
+ "<sign>822a379aec82755afaa9c63eea3b05b9</sign> "
+ "<errorCode></errorCode> "
+ "<errorMessage></errorMessage> " + "</SlotPermResult> "
+ "<SlotPermResult> "
+ "<appId>elbert_apx_dsc008</appId> "
+ "<slotIds></slotIds> " + "<time>1236586307734</time> "
+ "<sign>7ce9e326cb28b0084f7f331dcbb79f50</sign> "
+ "<errorCode></errorCode> "
+ "<errorMessage></errorMessage> " + "</SlotPermResult> "
+ "<SlotPermResult> "
+ "<appId>elbert_app_dsc008</appId> "
+ "<slotIds>elb_wsi_002</slotIds> "
+ "<time>1236586307734</time> "
+ "<sign>2ea135b978c75fb639fe65909283dcba</sign> "
+ "<errorCode></errorCode> "
+ "<errorMessage></errorMessage> "
+ "</SlotPermResult></SlotPermResult-array>";
List<String> Nodes = new ArrayList<String>();
Nodes.add("/SlotPermResult-array/SlotPermResult/appId");
Nodes.add("/SlotPermResult-array/SlotPermResult/slotIds");
Nodes.add("/SlotPermResult-array/SlotPermResult/errorCode");
Nodes.add("/SlotPermResult-array/SlotPermResult/errorMessage");
。。。。(在这里通过测试执行得到ActXmlTest)
assertEqualsNodes(ExpXmlText, ActXmlTest,Nodes);