C# 如何在XElement属性上使用LINQ Group by

C# 如何在XElement属性上使用LINQ Group by,c#,xml,linq,C#,Xml,Linq,var seriesfo包含以下XML <series id="S000002334Member"> <class id="C000006118Member" /> </series> <series id="S000002334Member"> <class id="C000006119Member" /> </series> 分组后需要XML: <se

var seriesfo
包含以下XML

    <series id="S000002334Member">
      <class id="C000006118Member" />
    </series>
    <series id="S000002334Member">
      <class id="C000006119Member" />
    </series>
分组后需要XML:

   <series id="S000002334Member">
      <class id="C000006118Member" />
      <class id="C000006119Member" />
    </series>


按不工作分组。

基本上,您需要按属性的(字符串)
值进行分组,而不是按属性本身进行分组

因为当您通过引用比较
XAttribute
s时,它们将被视为不同的,即使它们具有相同的文本值。所以分组不起作用

工作代码:

// (I added "root", otherwise the xml is invalid)
string original = "<root><series id=\"S000002334Member\"><class id=\"C000006118Member\" /></series><series id=\"S000002334Member\"><class id=\"C000006119Member\" /></series></root>";            
XElement originalXml = XElement.Parse(original);

var groups = originalXml              
    .Descendants("series")
    .GroupBy(a => a.Attribute("id").Value); // that's the important bit...

IEnumerable<XElement> afterGrouping = groups
    .Select(
        grp => // for each group...
            new XElement( // ...create a new element
                "series", 
                new XAttribute("id", grp.Key), 
                grp.Select(each => each.Element("class")))); // containing all "class" elements from the group

XElement final = new XElement("final", afterGrouping); // just adding root element again

// and the result is:
//
// <final>
//     <series id="S000002334Member">
//         <class id="C000006118Member" />
//         <class id="C000006119Member" />
//     </series>
// </final>
//(我添加了“root”,否则xml无效)
字符串original=“”;
XElement originalXml=XElement.Parse(原始);
变量组=原始XML
.后代(“系列”)
.GroupBy(a=>a.Attribute(“id”).Value);//这是最重要的一点。。。
IEnumerable afterGrouping=组
.选择(
grp=>//对于每个组。。。
新建元素(//…创建新元素
“系列”,
新XAttribute(“id”,组键),
grp.Select(each=>each.Element(“class”));//包含组中的所有“类”元素
XElement final=新XElement(“final”,后分组);//只是再次添加根元素
//结果是:
//
// 
//     
//         
//         
//     
// 

基本上,您需要根据属性的(字符串)
值进行分组,而不是属性本身

因为当您通过引用比较
XAttribute
s时,它们将被视为不同的,即使它们具有相同的文本值。所以分组不起作用

工作代码:

// (I added "root", otherwise the xml is invalid)
string original = "<root><series id=\"S000002334Member\"><class id=\"C000006118Member\" /></series><series id=\"S000002334Member\"><class id=\"C000006119Member\" /></series></root>";            
XElement originalXml = XElement.Parse(original);

var groups = originalXml              
    .Descendants("series")
    .GroupBy(a => a.Attribute("id").Value); // that's the important bit...

IEnumerable<XElement> afterGrouping = groups
    .Select(
        grp => // for each group...
            new XElement( // ...create a new element
                "series", 
                new XAttribute("id", grp.Key), 
                grp.Select(each => each.Element("class")))); // containing all "class" elements from the group

XElement final = new XElement("final", afterGrouping); // just adding root element again

// and the result is:
//
// <final>
//     <series id="S000002334Member">
//         <class id="C000006118Member" />
//         <class id="C000006119Member" />
//     </series>
// </final>
//(我添加了“root”,否则xml无效)
字符串original=“”;
XElement originalXml=XElement.Parse(原始);
变量组=原始XML
.后代(“系列”)
.GroupBy(a=>a.Attribute(“id”).Value);//这是最重要的一点。。。
IEnumerable afterGrouping=组
.选择(
grp=>//对于每个组。。。
新建元素(//…创建新元素
“系列”,
新XAttribute(“id”,组键),
grp.Select(each=>each.Element(“class”));//包含组中的所有“类”元素
XElement final=新XElement(“final”,后分组);//只是再次添加根元素
//结果是:
//
// 
//     
//         
//         
//     
// 

如果
系列中有一个
有多个子元素,我会选择这个。我的答案和这个答案之间的区别(除了我的答案更加循序渐进之外)在于使用
g.SelectMany(c=>c.substands(“class”)
我使用
grp.Select(each=>each.Element(“class”)
<
子体上的code>SelectMany
确保不会跳过
元素,而
Select
元素(“类”)
将只从每个
系列
中获取第一个
元素。对于OP给出的示例数据来说,这恰好没有什么区别,但是如果在某个
系列下有多个
@Damith-我正在向序列元素添加一个名为name的新属性,如何在输出中显示它?以及如何实现这样的东西,其中(s=>s.idList==“S0”)?如果
系列
中有一个
子元素,我会选择这个。我的答案和这个答案之间的区别(除了我的答案更加循序渐进之外)在于使用
g.SelectMany(c=>c.substands(“class”)
我使用
grp.Select(each=>each.Element(“class”)
<
子体上的code>SelectMany
确保不会跳过
元素,而
Select
元素(“类”)
将只从每个
系列
中获取第一个
元素。对于OP给出的示例数据来说,这恰好没有什么区别,但是如果在某个
系列下有多个
@Damith-我正在向序列元素添加一个名为name的新属性,如何在输出中显示它?以及如何实现这样的东西,其中(s=>s.idList==“S0”)?我正在向series元素添加一个名为name的新属性,如何在输出中显示它?我正在向series元素添加一个名为name的新属性,如何在输出中显示它?
var result = doc.Descendants("series").GroupBy(s => s.Attribute("id").Value)
            .Select(g => new XElement("series", new XAttribute("id", g.Key), 
                        g.SelectMany(c=>c.Descendants("class"))));