查找Linq中两个集合中不同的子元素

时间:2011-08-16 06:24:53

标签: linq c#-4.0 linq-to-xml

如何为此进行Linq查询?

我有两个xml文档,doc1.xml和doc2.xml。如何找到doc1中每个“file”元素,其中doc2的“file”元素具有完全相同的“path”属性,但doc1中此“文件”的任何“link”子元素都具有“absolutepath”属性,是不是与doc2中相应的“file”元素中的一个或多个“absolutepath”属性相同?

简单的例子:

DOC1:

<doc>
  <file path="c:\temp\A.xml">
    <link absolutepath="c:\temp\B.xml"/>
    <link absolutepath="c:\temp\C.xml"/>
  </file>
  <file path="c:\temp\C.xml"> <!--This should match, because it's child link absolutepath is not the same as child link absolutepath of the corresponding file with the same path in doc2-->
    <link absolutepath="c:\temp\D.xml"/>
    <link absolutepath="c:\temp\F.xml"/>
  </file>
</doc>

DOC2:

<doc>
  <file path="c:\temp\A.xml">
    <link absolutepath="c:\temp\B.xml"/>
    <link absolutepath="c:\temp\C.xml"/>
  </file>
  <file path="c:\temp\C.xml">
    <link absolutepath="c:\temp\D.xml"/>
    <link absolutepath="c:\temp\E.xml"/>
  </file>
</doc>

有什么想法吗?

编辑:编辑示例xml以显示每个文件元素的多个链接的含义。所以我想要的是doc1中的每个文件都有一个带有绝对路径的链接元素,该绝对路径在doc2的link元素中找不到。所以两者中实际上有相同数量的链接,但绝对路径有时会有所不同,这就是我想要找到的内容,并提取链接元素存在差异的那些文件。

这是我尝试修改Jon建议的查询,以提取多个链接,但我认为我做错了,因为我之后没有从Except查询中得到正确的结果:

   var files = from file in doc1.Descendants("file")

                select new
                {
                    file = file.Attribute("path").Value,
                    link = file.Elements("link").Attributes("absolutepath")
                };
    var oldfiles = from file in doc2.Descendants("file")
                from link in file.Elements("link")
                select new
                {
                    file = file.Attribute("path").Value,
                    link = file.Elements("link").Attributes("absolutepath")
                };
    //Get the ones that are different between them
    var missing = files.Except(oldfiles);

1 个答案:

答案 0 :(得分:2)

好吧,我将从XML部分开始。我最初认为这比它需要的更复杂,但我认为你可以使用:

var files = from file in document.Descendants("file")
            from link in file.Elements("link")
            select new { file = file.Attribute("path").Value,
                         link = link.Attribute("absolutepath").Value };

然后,如果您有files1files2(上述查询应用于每个文档),您可以这样做:

var extraFiles = files1.Except(files2);

编辑:要返回这些文件的链接元素,您可以使用:

var linkElements = from link in file.Descendants("link")
                   join extra in extraFiles on 
                         new { file = link.Parent.Attribute("path").Value,
                               link = link.Attribute("absolutepath").Value }
                         equals extra
                   select link;

再次查询文档有点遗憾,但我们去了......

(我选择了链接元素而不是文件元素,这样你就可以得到恰到好处的位 - 你总是可以选择父元素来获取文件。)

编辑:好的,如果有多个链接元素而您只是想找到缺少元素的文件,那实际上我们已经很容易了:

var justFiles = new HashSet<string>(extraFiles.Select(x => x.file).Distinct());
var fileElements = from element in file.Descendants("file")
                   where justFiles.Contains((string) element.Attribute("path")
                   select element;