【问题标题】:Populate class from an XML using Linq使用 Linq 从 XML 填充类
【发布时间】:2014-01-17 12:55:41
【问题描述】:

我有以下 XML

<?xml version="1.0" encoding="utf-8"?>
<Applications   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Blocks>
    <Block Name="block1">
        <Attributes>
            <Tag>Attribute1</Tag>
            <Layer>layer1</Layer>
        </Attributes>
        <Attributes>
            <Tag>Attribute2</Tag>
            <Layer>layer2</Layer>
        </Attributes>
    </Block>
    <Block Name="block2">
        <Attributes>
            <Tag>Attribute1</Tag>
            <Layer>layer0</Layer>
        </Attributes>
    </Block>
</Blocks>
</Applications>

我想使用 linq 语句来捕获所有详细信息并使用以下类填充列表。即列表

public class Block
{    
public string Tag { get; set; }
    public string Layer { get; set; }
}

我试过了……

List<Block> data =
(from a in xdoc.Root.Elements("Blocks")
where (string)a.Attribute("Name") == "block1"
select new Block
{
    Tag = (string)a.Element("Tag"),
    Layer = (string)a.Element("Layer")
}).ToList();

你能看出我哪里出错了吗,对 linq 来说有点陌生。

【问题讨论】:

  • 试试xdoc.Root.Elements("Blocks").Elements("block")
  • 道歉,我修改了原始 xml 以发布问题......因此出现错误

标签: c# xml linq


【解决方案1】:

试试:

LAMBDA 语法:

xdoc.Root.Elements("Blocks").Elements("Block")
    .Where(w => (string)w.Attribute("Name") == "block1")
    .Elements("Attributes")
    .Select(s => new Block
    {
        Tag = (string)s.Element("Tag"),
        Layer = (string)s.Element("Layer")
    });

如果你想使用查询语法:

from a in (from b in xdoc.Root.Elements("Blocks").Elements("Block")
        where (string)b.Attribute("Name") == "block1"
        select b).Elements("Attributes")
        select  new Block
        {
            Tag = (string)a.Element("Tag"),
            Layer = (string)a.Element("Layer")
        };

【讨论】:

  • 太棒了,谢谢大家的帮助 - 看起来工作得很好
【解决方案2】:

根据你的xml文档,我建议你改成这样:

public class Block
{    
   public string Name { get; set; }
   public List<BlockAttribute> Attributes { get; set; }
} 
public class BlockAttribute 
{  
   public string Tag { get; set; }
   public string Layer { get; set; }
}

然后使用这个代码:

var blocks = (from b in xdoc.Descendants("Block")
                 select new Block {
                          Name = (string)b.Attribute("Name"),
                          Attributes = (from a in b.Elements("Attributes")
                                           select new BlockAttribute {
                                                   Tag = (string)a.Element("Tag"),
                                                   Layer = (string)a.Element("Layer")
                                                  }).ToList()
                                    }).ToList();

【讨论】:

    【解决方案3】:

    你快到了。

    稍微修正一下你的 linq 语句:

    List<Block> data = (from a in (from b in xdoc.Root.Elements("Blocks").Elements("Block")
                                   where b.Attribute("Name").Value.Equals("block1")
                                   select b).Elements("Attributes")
                        select new Block()
                        {
                             Tag = a.Element("Attributes").Element("Tag").Value,
                             Layer = a.Element("Attributes").Element("Layer").Value
                        }).ToList();
    

    还要确保您的 XML 是有效的,因为您正在混合大小写。此外,根据@Grant-Winney 提到的,您的应用程序标签在您的示例中仍处于打开状态。

    【讨论】:

    • 查询仍然没有返回任何结果?
    • 如果您在 xml 中使用命名空间,您可能需要使用 XNamespace 对象将它们添加到查询中。见stackoverflow.com/questions/2340411/…
    • 好的,查询正常,但是它只返回一个属性值,而block1有2个属性
    • @user1641194 你最好使用 lambda 解决方案。它只是更简单。上述解决方案只会选择名为“属性”的第一个元素。在你得到你想要的东西之前,它需要进一步深入到 XElement 中。
    • 您的 block 类可以采用多个属性,还是您希望为 XML 中的每个块元素创建两个 block 对象?
    【解决方案4】:

    这应该可以完成工作。

            var blocks = xdoc.Descendants("Attributes").Select(x => new Block
                {
                    Tag = x.Descendants("Tag").Single().Value,
                    Layer = x.Descendants("Layer").Single().Value
                }).ToList();
    

    【讨论】:

    • Lambda 对 linq 新手来说通常很棘手,因为大多数人已经熟悉类似 SQL 的查询。虽然这在这种情况下可以工作,但根据 XML 的不同,它并不是很宽容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    相关资源
    最近更新 更多