【问题标题】:linq to xml initializing arraylinq to xml 初始化数组
【发布时间】:2011-02-09 20:21:24
【问题描述】:

我有两个类 - CdTrack 我正在尝试使用 Linq 从 XML 文件中读取它们。

public Cd(string t, string a, string cat, DateTime rls, Track[] tr)
public Track(string t, int l)

XML 看起来像这样。

奥兹·奥斯本对着月亮吠叫你与众不同现在你看到了(现在你没看到)Rock 'N' Roll Rebel永恒中心专辑> 旅程艺术家> 不要停止相信恋爱之石谁在哭泣继续奔跑专辑> 媒体>

我尝试使用的代码如下

XElement xdoc = XElement.Load("dbxml.xml"); var temp = 来自 xdoc.Descendants("cd") 中的 cds 选择新的镉( cds.Element("艺术家").Value, cds.Element("专辑").Attribute("Name").Value, cds.Element("专辑").Attribute("类型").Value, DateTime.Parse(cds.Element("album").Attribute("ReleaseDate").Value), new Track[] { // 一个音轨读取良好.. 新曲目(cds.Element(“专辑”).Element(“曲目”).Value, int.Parse(cds.Element("album").Element("track").Attribute("Length").Value)) } );

问题是我不知道如何使用从 XML 文件中读取的所有轨道初始化数组。我可以将整个查询包装在.ToList() 中,使用异常类型和foreach-it,但我想知道是否有一种方法可以在使用 linq 的一次运行中做到这一点。

cds.Elements("album").Elements("song") 返回一个IEnumerable<XElement> 集合,并且应该以某种方式将其作为范围添加到数组中并转换为字符串和int,或其他类似的东西。有什么帮助吗?

谢谢!

【问题讨论】:

    标签: c# xml linq-to-xml initialization anonymous-types


    【解决方案1】:

    这可行:

    XElement xdoc = XElement.Load("test.xml");
    var temp = from cds in xdoc.Descendants("cd")
                select new Cd(
                    cds.Element("artist").Value,
                    cds.Element("album").Attribute("Name").Value,
                    cds.Element("album").Attribute("Type").Value,
                    DateTime.Parse(cds.Element("album").Attribute("ReleaseDate").Value),
                    cds.Element("album").Descendants("track").Select(t => new Track(t.Value, int.Parse(t.Attribute("Length").Value))).ToArray() 
                    );
    

    使用属性更容易阅读(imo):

    select new Cd()
        {
            Artist = cds.Element("artist").Value,
            Album = cds.Element("album").Attribute("Name").Value,
            Type = cds.Element("album").Attribute("Type").Value,
            ReleaseDate = DateTime.Parse(cds.Element("album").Attribute("ReleaseDate").Value),
            Tracks = cds.Element("album")
                        .Descendants("track")
                        .Select(t => new Track()
                        {
                          Name = t.Value,
                          Length = int.Parse(t.Attribute("Length").Value)
                        }).ToArray()
        };
    

    您应该考虑为CdTrack 添加一个默认构造函数并公开公共属性或使用命名参数——这将使LINQ 语句更具可读性。

    【讨论】:

    • 开箱即用 - 谢谢!实际上,我确实有所有字段的默认构造函数和属性。您是否愿意详细说明如何通过使用属性来提高此查询的可读性?
    • 我发现作为阅读器的属性分配更容易解析,所以这可能是 select new Cd() { Artist = ... , Album = ... , },同样适用于 Tracks
    • 是的,这似乎是一个更具可读性的查询。谢谢!简而言之,我需要进一步研究我的 C#。 :-)
    【解决方案2】:

    在您的 LINQ 中,替换

    new Track[] { // One Track reads fine..
        new Track(cds.Element("album").Element("track").Value,
           int.Parse(cds.Element("album").Element("track").Attribute("Length").Value)) 
           }
    

    类似这样的:

    ( from t in cds.Element("album").Elements("track") 
      select new Track(..., ...)
    ).ToArray()
    

    【讨论】:

    • 谢谢!虽然我得到了每张专辑的第一首曲目,所有剩余曲目都重复了。五个在月球上吠叫和四个不要停止相信。也许我搞砸了什么?
    • 我打错了 Element 和 IIRC,它是您想要的 Elements。 BrokenGlass 的答案是使用 .Descendants,这可能是更好的方法。
    猜你喜欢
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-15
    相关资源
    最近更新 更多