Ramdeo angh Ramdeo angh - 1 month ago 5x
C# Question

How to process XML file into C# List<T> on conditional basis?

Here is my sample XML schema that is generated by SQL Server. I want it to assign to

in C# using LINQ. I tried it but I am getting six rows but after parsing this XML. I should get only one rows in list.

There some conditions to parse this XML.

  • TYPE == 1 then SMS,

  • TYPE == 3 then DATA

  • TYPE == 2 then MINUTES



Here is my C# class structure. I want to parse this XML schema into a
. After parsing this there will be only two rows into
. I have used
for XML parsing. After that, I am using Linq
method but I am getting six rows but output should contain only one rows.

public class UsageSummary
public int carrierID { get; set; }
public Int64 minutes { get; set; }
public Int64 sms { get; set; }
public Int64 data { get; set; }
public string period { get; set; }

I have used this code:

List<UsageSummary> obj = new List<UsageSummary>();

obj = (from res in xmlDoc.Descendants("summary")
select new UsageSummary
carrierID = (Convert.ToInt16(res.Element("providerid").Value)),
period = res.Element("period").Value.ToString(),
sms = (Convert.ToInt64(res.Element("SMS").Value)),
data = (Convert.ToInt64(res.Element("DATA").Value)),
minutes = (Convert.ToInt64(res.Element("MINUTES").Value))

Kindly help me with this problem.


You need to group your elements. You can split the problem into 3 parts so you're not trying to this all at once.

First, map your XML onto a structure that mirrors the XML structure:

var items =
    from summary in doc.Descendants("summary")
    select new
       Period = (string) summary.Element("period"),
       CarrierId = (int) summary.Element("providerid"),
       Type = (int) summary.Element("type"),
       Volume = (long) summary.Element("volume")

Then group these by CarrierId and Period. For Volume, you want a dictionary of all the volumes by Type:

var volumesByPeriodAndCarrier =
    from item in items
    group item by new {item.CarrierId, item.Period}
    into grouping
    select new
        VolumeByType = grouping.ToDictionary(x => x.Type, x => x.Volume)

Then you can easily create your summaries. CarrierId and Period map directly to your class, and the 3 volumes are where you use your mapping from types to fields:

var summaries = volumesByPeriodAndCarrier
    .Select(x => new UsageSummary
        carrierID = x.CarrierId,
        minutes = x.VolumeByType[2],
        sms = x.VolumeByType[1],
        data = x.VolumeByType[3],
        period = x.Period

See this fiddle for a working demo.