如何使用linq select组合两个XElements?

4

我正在尝试将两个XElements列表合并为一个:

var list1 = XElement.Parse(@"<root><Element name=""foo"">
                                        <ChildElement name=""childFoo"">
                                            <SubChildElement name=""subChildFoo"" />
                                        </ChildElement>
                                    </Element>
                                    <Element name=""bar"">
                                        <ChildElement name=""childBar"">
                                            <SubChildElement name=""subChildBar"" />
                                        </ChildElement>
                                    </Element>
                                    <Element name=""zoo"" /></root>").XPathSelectElements("Element").ToList();

var list2 = XElement.Parse(@"<root><Element name=""foo"" attr=""fooAtr"" />
                                    <Element name=""bar"" attr=""barAtr"" />
                                    <Element name=""zoo"" attr=""barAtr"" /></root>").XPathSelectElements("Element").ToList();

var res = from e2 in list2
           join e1 in list1
           on e2.Attribute("name").Value equals e1.Attribute("name").Value
           select new XElement(e1.Add(e2.Element("ChildElement")));

代码无法编译是因为 select 错误(XElement.Add() 返回 void)。

如何在 select 中组合 e1 和 e2 两个 XElement 并返回新的 XElement(e2 带有来自 e1 的子元素)。

我想获得以下格式的列表:

<Element name="foo" attr="fooAtr">
    <ChildElement name="childFoo">
        <SubChildElement name="subChildFoo" />
    </ChildEelement>
</Element>
<Element name="bar" attr="barAtr">
    <ChildElement name="childBar">
        <SubChildElement name="subChildBar" />
    </ChildEelement>
</Element>
<Element name="zoo" attr="barAtr" />
2个回答

5
我建议您放弃使用XPath,改用LINQ to XML查询方法来查找元素。您的select需要从第二个元素复制名称和属性,并从第一个元素复制子元素。
var results = from e2 in second.Descendants("Element")
              join e1 in first.Descendants("Element")
                  on (string)e2.Attribute("name") equals (string)e1.Attribute("name")
              select new XElement(e2.Name, e2.Attributes(), e1.Elements());

点击此处查看实际演示:https://dotnetfiddle.net/J3mcXu


1
这正是我一直在寻找的,非常好用,因为我可以将e1和e2的属性分组,并仍然使用构造函数。 - greenfeet

1
你之所以会出现错误,是因为 Select() 操作必须返回一个对象。实际上,你正在尝试在 Select() 操作内部执行 foreach,这不是它的用法。LINQ 不包括 foreach 操作,因为它可能具有副作用,所以你应该使用另一种方法。
编辑:我最初发布的内容会连接列表而不是合并它们。我本来想再发布一个答案,但 @Charles Mager 发布了最简单的解决方案。我仍然将此答案保留在这里,以解释为什么你尝试的 select 语句无法正常工作。

这只是将所有元素连接在一起 - 所需的是问题中显示的合并输出。 - Charles Mager

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接