【问题标题】:Test the value of an XML attribute to create an object测试 XML 属性的值以创建对象
【发布时间】:2014-04-29 09:47:59
【问题描述】:

我正在尝试使用 linq 从 XML 文件中获取数据,并将它们转换为对象。

但是我的 XML 文件中的一些数据是这样的:

<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>

我要做的是创建机器AAA,BBB,CCC和DDD。

目前,我的代码是:

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()
};

使用这种方法,我的 XML 文件中将拥有与“别名”一样多的“机器”。

有没有办法根据第二个“_”之前的字符创建对象“Machine”的单个实例

这段代码的目的是创建: 具有通道 1、2、3 的实例“Machine_AAA”, 具有通道 1、2、3 的实例“Machine_BBB”, 具有通道 1,2 的实例“Machine_CCC”, 具有通道 1 的实例“Machine_DDD”。

如果不清楚,我很抱歉,英语是我的第二语言,C# 是我的第三语言。

感谢您的回答。

【问题讨论】:

  • 您是否可以控制正在读取的 xml 文件?
  • 我无法更改 xml 文件。 :(

标签: c# linq xml-parsing linq-to-objects


【解决方案1】:

这样做的关键是使用下划线分割name 属性的值,然后按第二个元素(即机器名称)分组。下面是一个代码示例:

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);

【讨论】:

  • 嗨,抱歉耽搁了。最后我像你一样做到了。谢谢你的回答!
  • 嗨@tazinoufou,如果这个或任何答案已经解决了您的问题,请点击复选标记考虑accepting it。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。
猜你喜欢
  • 1970-01-01
  • 2015-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多