如何使用LINQ c#组合和更新两个xml文件

时间:2016-02-02 15:58:35

标签: c# xml linq

我想组合这些简单的xml文件:

result2.xml:

<?xml version="1.0" encoding="utf-8"?>
<Sports>
  <Sport id="1">
  </Sport>
</Sports>

result3.xml

<?xml version="1.0" encoding="utf-8"?>
<Sports>
  <Sport id="1">
  </Sport>
  <Sport id="2">   
  </Sport>
</Sports>

我正在尝试使用C#代码:

static void Main()
{
  XDocument xml1 = XDocument.Load("result2.xml");
  XDocument xml2 = XDocument.Load("result3.xml");

  var combinedUnique = xml1.Descendants("Sport")
                     .Union(xml2.Descendants("Sport"));

  foreach (var item in combinedUnique)
  {
     Console.WriteLine(item);
  }
}

我期望的结果是:

 <?xml version="1.0" encoding="utf-8"?>
    <Sports>
      <Sport id="1">
      </Sport>
      <Sport id="2">   
      </Sport>
    </Sports>

但我明白了:

 <?xml version="1.0" encoding="utf-8"?>
    <Sports>
      <Sport id="1">
      </Sport>                                                                                           
      <Sport id="1">
      </Sport>
      <Sport id="2">   
      </Sport>
    </Sports>

您能否提出如何使此C#代码适用于此特定情况? 我尝试了数组,它正在工作 提前致谢!

1 个答案:

答案 0 :(得分:2)

因此,即使元素的id属性共享相同的值,它们仍然是不同的对象,DistinctUnion不会被视为相等,只是因为有些任意属性值相等。

如果您需要执行&#34; distinctBy&#34;,您可以使用以下模式(对相关属性进行分组,然后从每个组中选择第一个元素):

var combinedUnique = xml1.Descendants("Sport")
                         .Concat(xml2.Descendants("Sport"))
                         .GroupBy(xe => (int)xe.Attribute("id"))
                         .Select(g => g.First());

请注意,我还将Union替换为Concat,因为Union完成的额外(基于设置的插入)工作对于这种情况无效,因此我们可以更高效地使用Concat(联合所有)。

将它包装成扩展方法可能是有意义的:

public static class LinqEx
{
    public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> src, 
                                                     Func<T, TKey> keySelector)
    {
        return src.GroupBy(keySelector).Select(g => g.First());
    }
}

所以现在你可以:

var combinedUnique = xml1.Descendants("Sport")
                         .Concat(xml2.Descendants("Sport"))
                         .DistinctBy(xe => (int)xe.Attribute("id"));