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