作为一些广泛的单元测试的基类的一部分,我正在编写一个辅助函数,它在C#(.NET)中递归地将一个XmlDocument对象的节点与另一个XmlDocument对象的节点进行比较。一些要求:
xsi:schemaLocation
和xmlns:xsi
,但我希望能够传递哪些内容。InnerText
,但不能同时包含子元素。虽然我正在废弃一些东西:有人写过这样的代码并且可以在这里分享吗?
暂且不说,你会把第一个和第二个文件称为什么?我一直把它们称为“来源”和“目标”,但感觉不对,因为来源是我想要目标的样子,否则我扔了例外。
答案 0 :(得分:53)
Microsoft有XML diff API您可以使用
答案 1 :(得分:7)
我今天搜索了一个更完整的问题解决方案列表,我很快就会尝试其中一个:
答案 2 :(得分:5)
比较XML文档很复杂。谷歌为xmldiff(甚至是微软的解决方案)提供一些工具。我已经通过几种方式解决了这个问题。我使用XSLT对元素和属性进行排序(因为有时候它们会以不同的顺序出现,我不关心它),并过滤掉我不想比较的属性,然后使用{{3} }或XML::Diff perl模块,或者将每个元素和属性打印在一个单独的行上,并在结果上使用Unix命令行diff。
答案 3 :(得分:5)
尝试XMLUnit。该库可用于Java和.Net
答案 4 :(得分:4)
此代码不能满足您的所有要求,但它很简单,我正在使用我的单元测试。属性顺序无关紧要,但元素顺序确实如此。元素内部文本未进行比较。我在比较属性时也忽略了大小写,但你可以轻松删除它。
public bool XMLCompare(XElement primary, XElement secondary)
{
if (primary.HasAttributes) {
if (primary.Attributes().Count() != secondary.Attributes().Count())
return false;
foreach (XAttribute attr in primary.Attributes()) {
if (secondary.Attribute(attr.Name.LocalName) == null)
return false;
if (attr.Value.ToLower() != secondary.Attribute(attr.Name.LocalName).Value.ToLower())
return false;
}
}
if (primary.HasElements) {
if (primary.Elements().Count() != secondary.Elements().Count())
return false;
for (var i = 0; i <= primary.Elements().Count() - 1; i++) {
if (XMLCompare(primary.Elements().Skip(i).Take(1).Single(), secondary.Elements().Skip(i).Take(1).Single()) == false)
return false;
}
}
return true;
}
答案 5 :(得分:3)
我使用ExamXML来比较XML文件。你可以尝试一下。 作者A7Soft还提供了用于比较XML文件的API
答案 6 :(得分:3)
https://github.com/CameronWills/FatAntelope Microsoft XML Diff API的另一个替代库。它有一个XML diffing算法,可以对两个XML文档进行无序比较,并产生最佳匹配。
这是此处描述的X-Diff算法的C#端口: http://pages.cs.wisc.edu/~yuanwang/xdiff.html
免责声明:我写了:)
答案 7 :(得分:2)
另一种方法是 -
这不会为您提供差异的确切位置,但如果您只是想知道是否存在差异,那么在没有任何第三方库的情况下这很容易做到。
答案 8 :(得分:2)
与OP无关,因为它目前忽略了子订单,但如果您想要一个仅限代码的解决方案,您可以尝试我XmlSpecificationCompare开发的somewhat misguidedly。
答案 9 :(得分:2)
在自动测试中比较两个XML输出时,我发现了XNode.DeepEquals
。
比较两个节点的值,包括所有后代节点的值。
用法:
var xDoc1 = XDocument.Parse(xmlString1);
var xDoc2 = XDocument.Parse(xmlString2);
bool isSame = XNode.DeepEquals(xDoc1.Document, xDoc2.Document);
//Assert.IsTrue(isSame);
参考:https://docs.microsoft.com/en-us/dotnet/api/system.xml.linq.xnode.deepequals?view=netcore-2.2
答案 10 :(得分:0)
基于@Two Cents回答并使用此链接XMLSorting我创建了自己的XmlComparer
比较XML程序
private static bool compareXML(XmlNode node, XmlNode comparenode)
{
if (node.Value != comparenode.Value)
return false;
if (node.Attributes.Count>0)
{
foreach (XmlAttribute parentnodeattribute in node.Attributes)
{
string parentattributename = parentnodeattribute.Name;
string parentattributevalue = parentnodeattribute.Value;
if (parentattributevalue != comparenode.Attributes[parentattributename].Value)
{
return false;
}
}
}
if(node.HasChildNodes)
{
sortXML(comparenode);
if (node.ChildNodes.Count != comparenode.ChildNodes.Count)
return false;
for(int i=0; i<node.ChildNodes.Count;i++)
{
string name = node.ChildNodes[i].LocalName;
if (compareXML(node.ChildNodes[i], comparenode.ChildNodes[i]) == false)
return false;
}
}
return true;
}
排序XML程序
private static void sortXML(XmlNode documentElement)
{
int i = 1;
SortAttributes(documentElement.Attributes);
SortElements(documentElement);
foreach (XmlNode childNode in documentElement.ChildNodes)
{
sortXML(childNode);
}
}
private static void SortElements(XmlNode rootNode)
{
for(int j = 0; j < rootNode.ChildNodes.Count; j++) {
for (int i = 1; i < rootNode.ChildNodes.Count; i++)
{
if (String.Compare(rootNode.ChildNodes[i].Name, rootNode.ChildNodes[1 - 1].Name) < 0)
{
rootNode.InsertBefore(rootNode.ChildNodes[i], rootNode.ChildNodes[i - 1]);
}
}
}
// Console.WriteLine(j++);
}
private static void SortAttributes(XmlAttributeCollection attribCol)
{
if (attribCol == null)
return;
bool changed = true;
while (changed)
{
changed = false;
for (int i = 1; i < attribCol.Count; i++)
{
if (String.Compare(attribCol[i].Name, attribCol[i - 1].Name) < 0)
{
//Replace
attribCol.InsertBefore(attribCol[i], attribCol[i - 1]);
changed = true;
}
}
}
}
答案 11 :(得分:0)
我编写了这个基于XSLT 1.0的比较表,您可以将b.xml与输入xml输出输出中不在b.xml中的项的差异进行比较。
答案 12 :(得分:0)
以上所有答案都有帮助,但我尝试了 XMLUnit,它看起来很容易使用 Nuget 包来检查两个 XML 文件之间的差异,这里是 C# 示例代码
public static bool CheckXMLDifference(string xmlInput, string xmlOutput)
{
Diff myDiff = DiffBuilder.Compare(Input.FromString(xmlInput))
.WithTest(Input.FromString(xmlOutput))
.CheckForSimilar().CheckForIdentical()
.IgnoreComments()
.IgnoreWhitespace().NormalizeWhitespace().Build();
if(myDiff.Differences.Count() == 0)
{
// when there is no difference
// files are identical, return true;
return true;
}
else
{
//return false when there is 1 or more difference in file
return false;
}
}
如果有人想测试它,我也使用它创建了在线工具,您可以在这里查看