iTunes・ライブラリのエクスポートで得られるXMLファイルをパースするためのC#のクラス群。
アルバム(Albumクラス)と曲(Tuneクラス) と<dict>要素をラップするXDictクラスを定義。
using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Xml; using System.Linq; using System.Xml.Linq; using System.Xml.XPath; class Tune { public long Id; public string Name; public string Artist; public int Track; public long Size; public TimeSpan Time; public string Kind; public string Album; public Tune(XDict xDict) { this.Id = (long)xDict["Track ID"]; this.Name = xDict["Name"] as string; this.Size = (long)xDict["Size"]; this.Time = (TimeSpan)xDict["Total Time"]; this.Kind = xDict["Kind"] as string; this.Artist = xDict["Artist"] != null ? xDict["Artist"] as string : "None"; this.Album = xDict["Album"] != null ? xDict["Album"] as string : ""; this.Track = xDict["Track Number"] != null ? (int)xDict["Track Number"] : 0; } } enum SortBy { Time,Track,Name,Size } class Album { private Comparison<Tune>[] CompareBy = new Comparison<Tune>[4] { (x,y) => (int)((x.Time - y.Time).Ticks), //再生時間でソート (x,y) => x.Track - y.Track, //トラックナンバーでソート (x,y) => string.Compare(x.Name,y.Name), //曲名でソート (x,y) => (int)(x.Size - y.Size) //サイズでソート }; public List<Tune> Tunes = new List<Tune>(); public string Name; public string Artist; public Album(Tune tune) { this.Name = tune.Album; this.Tunes.Add(tune); } public Album(string name,string artist) { this.Name = name; this.Artist = artist; } public void Sort(SortBy b) { this.Tunes.Sort(this.CompareBy[(int)b]); } } class XDict { private Dictionary<string,object> Element = new Dictionary<string,object>(); private Dictionary<string,XDict> Dict = new Dictionary<string,XDict>(); private Dictionary<string,IEnumerable<XDict>> Dicts = new Dictionary<string,IEnumerable<XDict>>(); ///<summary>キー一覧</summary> public string[] Keys { get { return this.Element.Keys.ToArray(); } } ///<summary>インデクサ</summary> public object this[string key] { get { return this.Element.ContainsKey(key) ? this.Element[key] : null; } set { if(!Element.ContainsKey(key)) Element[key] = value; } } ///<summary>要素数</summary> public int Length { get { return this.Element.Count(); } } ///<summary>コンストラクタ</summary> public XDict(XElement el) { this.Parse(el); } public XDict(string file,string xpath) { if(!File.Exists(file)) throw new Exception("ファイルが存在しません"); var xRoot = XElement.Load(file); var xRootDict = xRoot.XPathSelectElement(xpath); this.Parse(xRootDict); } ///<summary> /// dict要素(XElement)を渡して、子要素を取得していき、 /// メンバーフィールドのElementを埋めていきます。 ///</summary> private void Parse(XElement elm) { if(elm.Name.LocalName != "dict") return; var elms = elm.Elements(); int num = elms.Count(); var enumerator = elms.GetEnumerator(); for(int i = 0;i < num;i += 2) { enumerator.MoveNext(); string key = enumerator.Current.Value; enumerator.MoveNext(); XElement el = enumerator.Current; string typename = el.Name.LocalName; if( typename == "dict" ) { this.Element[key] = this.Dict[key] = new XDict(el); } else if(typename == "array") { this.Element[key] = this.Dicts[key] = from e in el.Elements() select new XDict(e); } else { object obj = null; string val = el.Value; switch(typename) { case "integer": { switch(key) { case "Track Number": obj = int.Parse(val); break; case "Total Time": obj = TimeSpan.FromMilliseconds(long.Parse(val)); break; default: obj = long.Parse(val); break; } } break; case "string": obj = val; break; case "date": obj = DateTime.Parse(val); break; case "true": case "false": obj = bool.Parse(typename); break; } this.Element[key] = obj; } } } }