Search code examples
c#.netxmllinq-to-xmlnested-groups

3 nested groups with linq


I am trying to get 4 List deep List collection, List<List<List<List<int>>>>. From my Xml which looks like

<root> 
    <Claim key="1" carrier="carA" zip="34343" pages="1"/>
    <Claim key="2" carrier="carA" zip="34343" pages="2"/>
    <Claim key="3" carrier="carB" zip="10505" pages="2"/>
    <Claim key="4" carrier="carB" zip="10505" pages="4"/> 
    <Claim key="5" carrier="carB" zip="10505" pages="4"/>
</root>

the structure of the output should look like

-all
   -1
       -34343
           -carA
                   -1

   -2
       -34343
           -carA
                   -2

       -10505
               -carB
                   -3
   -4
       -10505
           -carB
                    -4
                    -5

the goal is to sort my XML based on the node attributes first by number of pages, then by zip, then by carrier. I will then need to cycle through the result list and process each claim in the particular order. I am having trouble getting the syntax right for 3 nested groups. I have accomplished getting 2 nested groups can anyone help me get the third.

here is my code so far.

var query = from claim in root.Elements("Claim")
                        group claim by claim.Attributes("Pages").First().Value into pageGroups
                        from zipGroups in
                            (from claim in pageGroups
                             group claim by int.Parse(claim.Attributes("CarrierZip").First().Value))
                        group zipGroups by pageGroups.Key;

Solution

  • If nothing else I believe this code answers your question. Having to handle four nested lists is pretty complex and if you can refactor your solution into something simpler you will probably find that your code will be easier to maintain.

    var xml = @"<root>  
      <Claim key=""1"" carrier=""carA"" zip=""34343"" pages=""1""/> 
      <Claim key=""2"" carrier=""carA"" zip=""34343"" pages=""2""/> 
      <Claim key=""3"" carrier=""carB"" zip=""10505"" pages=""2""/> 
      <Claim key=""4"" carrier=""carB"" zip=""10505"" pages=""4""/>  
      <Claim key=""5"" carrier=""carB"" zip=""10505"" pages=""4""/>
    </root>";
    
    var xElement = XElement.Parse(xml);
    
    var claims = xElement
      .Elements("Claim")
      .Select(
        x => new {
          Key = (Int32) x.Attribute("key"),
          Carrier = (String) x.Attribute("carrier"),
          Zip = (Int32) x.Attribute("zip"),
          Pages = (Int32) x.Attribute("pages")
        }
      );
    
    var lists = claims
      .OrderBy(claim => claim.Pages)
      .GroupBy(claim => claim.Pages)
      .Select(pagesGroup => pagesGroup
        .OrderBy(claim => claim.Zip)
        .GroupBy(claim => claim.Zip)
        .Select(zipGroup => zipGroup
          .OrderBy(claim => claim.Carrier)
          .GroupBy(claim => claim.Carrier)
          .Select(carrierGroup => carrierGroup
            .OrderBy(claim => claim.Key)
            .Select(claim => claim.Key)
            .ToList()
          )
          .ToList()
        )
        .ToList()
      )
      .ToList();