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

发布于 2024-11-29 12:11:03 字数 2009 浏览 0 评论 0原文

我该如何为此执行 Linq 查询?

我有两个 xml 文档:doc1.xml 和 doc2.xml。如何找到 doc1 中的每个“文件”元素,其中 doc2 有一个具有完全相同的“路径”属性的“文件”元素,但 doc1 中此“文件”的任何“链接”子元素都有一个“绝对路径”属性与 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 中的链接元素中找不到该绝对路径。因此,两者实际上有相同数量的链接,但绝对路径有时可能不同,这就是我想要查找并提取链接元素存在差异的那些文件。

这是我尝试修改 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);

How can I do a Linq query for this?

I have two xml documents, doc1.xml, and doc2.xml. How can I find for each "file" element in doc1 where doc2 has a "file" element with the exact same "path" attribute, but any "link" child element of this "file" in doc1 has an "absolutepath" attribute that is NOT the same as one or more "absolutepath" attributes in the corresponding "file" element in doc2?

simple example:

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>

Any ideas?

EDIT: Edited the example xml to show what I mean by multiple links for each file element. So what I want is each file in doc1 that has a link element with an absolutepath that is not found in a link element in doc2. So there are actually the same number of links in both, but the absolutepath may differ sometimes and that's what I want to find and extract those files where there is such a difference in the link elements.

Here's my attempt to modify the query suggested by Jon, to extract multiple links, but I think I'm doing it wrong, because I don't get the correct result from the Except query afterwards:

   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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迷乱花海 2024-12-06 12:11:03

好吧,我将从 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;

Well, I would start with the XML part. I originally made this more complicated than it needs to be, but I think you can just use:

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 };

Then if you have files1 and files2 (the above query applied to each document) you can just do:

var extraFiles = files1.Except(files2);

EDIT: To get back to the link elements for those files, you can use:

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;

It's a bit of a shame to query the document again, but there we go...

(I've selected the link element rather than the file element so you can get to exactly the right bit - you can always choose the parent element to get to the file.)

EDIT: Okay, if there are multiple link elements and you just want to find files with missing elements, that's actually pretty easy from what we've got:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文