Question

I'm trying to use linq to get data from an XML file, and convert them into objects.

But some of my data in my XML file are like this:

<XMLFILE>
    <Machines>
            <Alias name="MACHINE_AAA_1" />
            <Alias name="MACHINE_AAA_2" />
            <Alias name="MACHINE_AAA_3" />
            <Alias name="MACHINE_BBB_1" />
            <Alias name="MACHINE_BBB_2" />
            <Alias name="MACHINE_BBB_3" />
            <Alias name="MACHINE_CCC_1" />
            <Alias name="MACHINE_CCC_2" />
            <Alias name="MACHINE_DDD_1" />
    </Machines>
</XMLFILE>

What I want to do is to create machines AAA,BBB,CCC and DDD.

Currently, my code is :

Data DataMachines= new Data
{
    Machines = (from _alias in XEle.Elements("Machines").Elements("Alias")
                where _alias.Attribute("name").Valeur.Contains("MACHINE_")
                select new Machine
                {
                    Name=(string)_alias.Attribute("name").Value             
                }).ToList()
};

With this method I will have as many "Machines" as there is "Alias" in my XML file.

Is there a way to create a single instance of an object "Machine" according to the characters before the second "_" ?

The purpose of this code is to create: an instance "Machine_AAA" with channels 1,2,3, an instance "Machine_BBB" with channels 1,2,3, an instance "Machine_CCC" with channels 1,2, an instance "Machine_DDD" with channel 1.

I'm sorry if it's not clear, english being my second language and C# my third.

Thank you for answers.

Was it helpful?

Solution

The key to this is to split the value of the name attribute using underscores then group by the second element, which is the machine name. Here is a code sample which does just that:

const string machinesXml = @"<XMLFILE>
    <Machines>
        <Alias name=""MACHINE_AAA_1"" />
        <Alias name=""MACHINE_AAA_2"" />
        <Alias name=""MACHINE_AAA_3"" />
        <Alias name=""MACHINE_BBB_1"" />
        <Alias name=""MACHINE_BBB_2"" />
        <Alias name=""MACHINE_BBB_3"" />
        <Alias name=""MACHINE_CCC_1"" />
        <Alias name=""MACHINE_CCC_2"" />
        <Alias name=""MACHINE_DDD_1"" />
    </Machines>
</XMLFILE>";

var XEle = XElement.Parse(machinesXml);

// Locate the machines element
var machinesElement = XEle.Element("Machines");

// Split the name
var splitAliasNames = machinesElement.Elements("Alias").Select(a => a.Attribute("name").Value.Split('_'));

// Only take those where the split elements are what we expect
var ofCorrectParts = splitAliasNames.Where(split => split.Length == 3 &&
                                        "MACHINE".Equals(split[0], StringComparison.OrdinalIgnoreCase));

var channelForMachine = ofCorrectParts.Select(split => new
{
    MachineName = split[1], 
    ChannelName = split[2]
});

var byMachineName = channelForMachine.GroupBy(s => s.MachineName, StringComparer.OrdinalIgnoreCase);
var machines = byMachineName.Select(g =>
    {
        var channels = g.Select(s => s.ChannelName).ToList();
        return new Machine
        {
            Name = g.Key,
            Channels = channels
        };
    });

foreach (var machine in machines)
{
    Console.WriteLine("Machine '{0}':", machine.Name);
    foreach (var channel in machine.Channels)
    {
        Console.WriteLine("\tChannel '{0}'", channel);
    }
}
Console.ReadKey(true);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top