如果我想比较一个XML文档的内容,是不是就像这样做?
XmlDocument doc1 = GetDoc1();
XmlDocument doc2 = GetDoc2();
if(doc1 == doc2)
{
}
我不是在检查它们是否是同一个对象引用,而是检查xml的内容是否相同。
如果我想比较一个XML文档的内容,是不是就像这样做?
XmlDocument doc1 = GetDoc1();
XmlDocument doc2 = GetDoc2();
if(doc1 == doc2)
{
}
我不是在检查它们是否是同一个对象引用,而是检查xml的内容是否相同。
试试在XLinq API上使用DeepEquals方法。
XDocument doc1 = GetDoc1();
XDocument doc2 = GetDoc2();
if(XNode.DeepEquals(doc1, doc2))
{
}
不,XmlDocument没有覆盖Equals()
方法的行为,因此实际上只执行引用相等性-这在您的示例中将失败,除非文档实际上是相同的对象实例。
如果你想比较一个文档的内容(属性、元素、注释、PI等),你必须自己实现逻辑。请注意:这并不容易。
根据您的具体情况,您可以从文档中删除所有非必要的空格(这本身可能很棘手),然后比较生成的xml文本。这并不完美-对于在语义上相同但在使用和声明命名空间的方式、某些值是否转义或者元素顺序等方面略有不同的文档会失败。正如我之前所说,XML比较并不简单。
你还需要清楚地定义两个XML文档“相同”的含义。元素或属性排序重要吗?大小写(在文本节点中)有关系吗?应该忽略多余的CDATA部分吗?处理指令算吗?全限定与部分限定的命名空间呢?
在任何通用的实现中,您可能需要将两个文档转换为一些规范形式(无论是XML还是其他表示形式),然后比较规范化的内容。
已经存在执行XML差异的工具,如Microsoft XML Diff/Patch,您可以利用它来识别两个文档之间的差异。据我所知,该工具未以源代码形式分发...因此,在嵌入式应用程序中使用它,您需要编写脚本过程(如果您计划使用它,请首先验证许可条款是否允许使用和再发布)。
编辑:如果你正在使用.NET 3.5 SP1,查看@Max Toro的回答,因为显然在XLinq中有一个选项可能会有所帮助。很高兴知道它的存在。
一个简单的方法是比较 OuterXml
。
var a = new XmlDocument();
var b = new XmlDocument();
a.LoadXml("<root foo='bar' />");
b.LoadXml("<root foo='bar'/>");
Debug.Assert(a.OuterXml == b.OuterXml);
通常您希望比较以不同顺序排列的XML字符串。使用此代码可以轻松完成。
class Testing
{
[Test]
public void Test()
{
Assert.AreEqual(
"<root><a></a><b></b></root>".SortXml()
, "<root><b></b><a></a></root>".SortXml());
}
}
public static class XmlCompareExtension
{
public static string SortXml(this string @this)
{
var xdoc = XDocument.Parse(@this);
SortXml(xdoc);
return xdoc.ToString();
}
private static void SortXml(XContainer parent)
{
var elements = parent.Elements()
.OrderBy(e => e.Name.LocalName)
.ToArray();
Array.ForEach(elements, e => e.Remove());
foreach (var element in elements)
{
parent.Add(element);
SortXml(element);
}
}
}
LBushkin说得对,这并不是一件简单的事情。由于XML是字符串数据,你可以在技术上对内容进行哈希处理并进行比较,但这会受到诸如空格之类的影响。
你可以执行结构化差异(也称为“XML diffgram”)来比较两个文档之间的差异。例如,这就是.NET数据集跟踪更改的方式。
除此之外,你还需要遍历DOM并将元素、属性和值相互比较。如果涉及模式,则还必须考虑位置等因素。
我知道这个问题有多老,但我不得不查阅多个来源才找到我要找的答案。以下是使用XNode.DeepEquals但也忽略属性顺序的方法。在经过了13年后,我为了得出这个答案所做的工作量,我想其他人可能会发现这个答案很有帮助。
使用NUnit作为我的测试套件,您可以传入两个XmlDocuments或一个XmlDocument和字符串。这将把XmlDocuments转换为XDocuments,对每个节点进行属性排序,然后执行XNode.DeepEquals()。
Assert.That(XmlHelperService.XMLCompare(xmlDoc, expectedStr), Is.EqualTo(true));
Assert.That(XmlHelperService.XMLCompare(xmlDoc, expectedXmlDoc), Is.EqualTo(true));
public class XmlHelperService
{
public static bool XMLCompare(XmlDocument primary, string secondaryStr)
{
XmlDocument secondary = new XmlDocument();
secondary.LoadXml(secondaryStr);
return XMLCompare(primary, secondary);
}
public static bool XMLCompare(XmlDocument primary, XmlDocument secondary)
{
return XNode.DeepEquals(NormalizeXElement(primary.ToXDocument().Root), NormalizeXElement(secondary.ToXDocument().Root));
}
private static XElement NormalizeXElement(XElement element)
{
return new XElement(element.Name,
element.Attributes().OrderBy(x => x.Name.ToString()),
element.Nodes().Select(n =>
{
XElement e = n as XElement;
if (e != null)
return NormalizeXElement(e);
return n;
})
);
}
}
public static class DocumentExtensions
{
public static XDocument ToXDocument(this XmlDocument xmlDocument)
{
using (var nodeReader = new XmlNodeReader(xmlDocument))
{
nodeReader.MoveToContent();
return XDocument.Load(nodeReader);
}
}
}