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.

Était-ce utile?

La 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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top