2011-02-09 25 views
0

私はLinqを使ってXMLファイルから読み込もうとしているCdTrackの2つのクラスを持っています。linq to xml初期化配列

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

XMLは次のようになります。問題は、私はXMLファイルから読み込むすべてのトラックで配列を初期化する方法がわからないということです

 
XElement xdoc = XElement.Load("dbxml.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), 
     new Track[] { // One Track reads fine.. 
      new Track(cds.Element("album").Element("track").Value, 
       int.Parse(cds.Element("album").Element("track").Attribute("Length").Value)) 
       } 
     ); 

を次のように

 
<media> 
    <cd> 
    <artist>Ozzy Osbourne</artist> 
    <album Name="Bark at the moon" Type="Metal" Tracks="5" ReleaseDate="1983-12-10"> 
     <track Length="300">Bark at the moon</track> 
     <track Length="235">You're No Different</track> 
     <track Length="567">Now You See It (Now You Don't)</track> 
     <track Length="356">Rock 'N' Roll Rebel</track> 
     <track Length="120">Centre of Eternity</track> 
    </album> 
    </cd> 
    <cd> 
    <artist>Journey</artist> 
    <album Name="Escape" Type="Rock" Tracks="4" ReleaseDate="1981-07-31"> 
     <track Length="300">Don't Stop Believin'</track> 
     <track Length="235">Stone in Love</track> 
     <track Length="567">Who's Crying Now</track> 
     <track Length="356">Keep on Runnin'</track> 
    </album> 
    </cd> 
</media> 

私が使用しようとしているコードがあります。私は.ToList()でクエリ全体をラップすることができます、無名型とforeach -itを使用しますが、linqを使って実行するだけでこれを行う方法があるかどうかを知りたいと思います。

cds.Elements("album").Elements("song")IEnumerable<XElement>のコレクションを返します。何とかして配列に範囲として追加し、文字列と整数などに変換する必要があります。そこに助けがありますか?

ありがとうございます!あなたのLINQで

答えて

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文がはるかに読みやすくなります。

+0

これは箱から出ました - ありがとう!私は実際にすべてのフィールドのデフォルトコンストラクタとプロパティを持っています。プロパティを使用してこのクエリをより読みやすくする方法について詳しく説明しますか? – citizencane

+0

私はプロパティの割り当てが読者として解析しやすくなっているので、これは '新しいCd(){Artist = ...、Album = ...、}'、トラックと同じです – BrokenGlass

+0

はい、より読みやすいクエリー。ありがとうございました!私はもう少し簡単にC#を勉強する必要があります。 :-) – citizencane

0

、このようなもので

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() 
+0

ありがとうございます!私はすべての残りのトラックのために繰り返されるすべてのアルバムの最初のトラックを得た。月の5つの樹皮と4つの信念を止めないでください。多分私は何かを台無しにした? – citizencane

+0

私は要素とIIRCをタイプミスしました。あなたが望む要素です。 BrokenGlassの答えは、よりよい方法かもしれない.Descendantsを使っています。 – ongle