使用LINQ to XML以编程方式获取两个XML文件之间的所有差异

本文关键字:XML 之间 文件 两个 to LINQ 编程 方式 使用 获取 | 更新日期: 2023-09-27 18:10:14

我使用c sharp 5.0并使用LINQ to XML,我尝试以编程方式获得2个XML文件之间的差异我的第一个文件很简单:

<?xml version="1.0" encoding="UTF-8" ?> 
<table name="MYTABLE">
<columns>
<column name="MY_ID" type="NUMBER"/> 
<column name="M_NAME" type="VARCHAR2" /> 
<column name="MY_PARENT_ID" type="VARCHAR2" /> 
<column name="MY_CAPTION" type="VARCHAR2" />
</columns>
</table>

和我的第二个XML文件一样简单:

<?xml version="1.0" encoding="UTF-8" ?> 
<table name=" MYTABLE ">
<columns>
<column name="MY_ID" type="NUMBER"/> 
<column name="M_NAME" type="VARCHAR2" /> 
<column name="MY_PARENT_ID" type="NUMBER" />
</columns>
</table>

和我的代码一样简单:

XDocument doc1 = XDocument.Load(@"Path'table1.xml");
XDocument doc2 = XDocument.Load(@"Path'table2.xml");
var cols1 = doc1.Descendants("column") ;
var cols2 = doc2.Descendants("column") ;
var itemsOnFirstFileOnly = cols1.Except(cols2);
var itemsOnSecondFileOnly = cols2.Except(cols1);

但令我惊讶的是itemsOnFirstFileOnly返回了存在于table1.xml上的所有列(不仅仅是MY_PARENT_ID &my_title)和itemsOnSecondFileOnly返回所有列存在于table2.xml(不仅仅是MY_PARENT_ID),所以为什么不除了不像预期的那样工作?

使用LINQ to XML以编程方式获取两个XML文件之间的所有差异

您必须在Column -class上实现Equals,以便Except知道两个Columns何时相等:

class Column 
{
    bool Equals(object other) 
    {
        // ...
        // skip further checks for simplicity
        // ...
        Column o = (Column) other;
        return o.Name == this.Name && o.Type == this.Type  ;
    }
}

如果你不实现这个方法,Except将检查引用相等,这永远不可能是真的,因为你的列来自不同的上下文(在你的情况下是文件)。

编辑:当你比较XNodes时,事情要容易得多,因为你可以使用XNodeEqualityComparer类,它有自己的Equals实现,完全符合你的需求,如这里所示。因此下面的代码应该可以工作:

var itemsOnFirstFileOnly = cols1.Except(cols2, new XNodeEqualityComparer());

你可以使用Linq:

var itemsOnFirstFileOnly = cols1.Where(x => !cols2.Select(y => y.Attribute("name").Value).Contains(x.Attribute("name").Value));
var itemsOnSecondFileOnly = cols2.Where(x => !cols1.Select(y => y.Attribute("name").Value).Contains(x.Attribute("name").Value));

基本上在上面的代码中:

  • 选择name属性的值
  • 比较这些名称
  • 返回名称在其他集合中缺失的XElement实例。

您还可以将XElement s转换为字符串,这会考虑到属性:

XDocument doc = XDocument.Parse(xml);
XDocument doc2 = XDocument.Parse(xml2);
var diffs = doc.Descendants().Select(e => e.ToString())
            .Except(doc2.Descendants().Select(e => e.ToString()));
foreach (var e in diffs)
{
    Console.WriteLine(e);
    Console.WriteLine();
}

考虑列,这只返回

<column name="MY_PARENT_ID" type="VARCHAR2" />
<column name="MY_CAPTION" type="VARCHAR2" />