如何在LINQ to XML中对值进行分组/求和?

时间:2017-07-05 20:42:26

标签: c# xml linq

我一直在尝试通过此工作,但我遇到了分组数据的问题。 我有一个XML结构

<FILE>
    <PLAN>
      <PLAN_ID>001</PLAN_ID>
      <PARTICIPANT>
        <PARTICIPANT_ID>9999</PARTICIPANT_ID>
        <INVESTMENTS>
          <INVESTMENT>
            <INVESTMENT_ID>ABC</INVESTMENT_ID>
            <BALANCE>1000</BALANCE>
            <ELECTION>0.00</ELECTION>
          </INVESTMENT>
          <INVESTMENT>
            <INVESTMENT_ID>XYZ</INVESTMENT_ID>
            <BALANCE>2000</BALANCE>
            <ELECTION>0.00</ELECTION>
          </INVESTMENT>
          <INVESTMENT>
            <INVESTMENT_ID>QWERTY</INVESTMENT_ID>
            <BALANCE>3000</BALANCE>
            <ELECTION>100.0</ELECTION>
          </INVESTMENT>
        </INVESTMENTS>
      </PARTICIPANT>
    </PLAN>
    <PLAN>
      <PLAN_ID>002</PLAN_ID>
      <PARTICIPANT>
        <PARTICIPANT_ID>9999</PARTICIPANT_ID>
        <INVESTMENTS>
          <INVESTMENT>
            <INVESTMENT_ID>ABC</INVESTMENT_ID>
            <BALANCE>2000</BALANCE>
            <ELECTION>0.00</ELECTION>
          </INVESTMENT>
          <INVESTMENT>
            <INVESTMENT_ID>XYZ</INVESTMENT_ID>
            <BALANCE>4000</BALANCE>
            <ELECTION>0.00</ELECTION>
          </INVESTMENT>
          <INVESTMENT>
            <INVESTMENT_ID>QWERTY</INVESTMENT_ID>
            <BALANCE>6000</BALANCE>
            <ELECTION>100.0</ELECTION>
          </INVESTMENT>
        </INVESTMENTS>
      </PARTICIPANT>
    </PLAN>
</FILE>

我开始尝试获取所有BALANCE元素的SUM

var doc = XDocument.Load("test.xml");

var sum = (from nd in doc.Descendants("BALANCE")
           select Int32.Parse(nd.Value)).Sum();

Console.WriteLine(sum);

并且有效,给了我18000.然后我想通过PLAN_ID对数据进行分组,但我不能让它给我0以外的其他数据。

var doc = XDocument.Load("test.xml");
var q = from x in doc.Descendants("PLAN")
        group x by x.Element("PLAN_ID").Value into gr
        select new
        {
             key = gr.Key,
             tot = (from tx in gr.Elements("BALANCE")
                    select (int)tx).Sum()
        };

当我跑步时,我得到:

  
      
  • [0] {key =“001”,tot = 0}
  •   
  • [1] {key =“002”,tot = 0}
  •   

我哪里出错了?

1 个答案:

答案 0 :(得分:1)

问题在于,当您要查找的元素比单个级别更深入XML树时,您正在使用Elements()。如果您在内部查询中切换到Descendants(),那么您应该得到您期望的结果。

var doc = XDocument.Load("test.xml");
var q = from x in doc.Descendants("PLAN")
        group x by x.Element("PLAN_ID").Value into gr
        select new
        {
             key = gr.Key,
             tot = (from tx in gr.Descendants("BALANCE")
                    select (int)tx).Sum()
        };

BALANCE节点比每个PLAN节点的内部节点深3个节点,所以这应该可以解决问题。

就个人而言,我喜欢使用lambda版本,因为它更清晰,所以只是为了完整性,这里使用lambda语法的相关解决方案:

var q = doc.Descedants("PLAN")
         .GroupBy(x => x.Element("PLAN_ID").Value))
         .Select(gr => new 
         {
             key = gr.Key,
             tot = gr.Sum(tx => (int)tx.Descendants("BALANCE"))
         });