2010年01月14日

2008年12月14日

XContainer.Descendants メソッド

   このエントリーをはてなブックマークに追加 Clip to Evernote
Descendants()メソッド。

おおっ、こんなメソッドがあったのか?
LINQ to XMLの紹介の記事では、このメソッドが紹介されているのを 見たことなかったので、 今まで存在を知らなかった orz...
確かに、DOMのGetElementsByTagName に該当するメソッドがなかったら、面倒でしかたないですからね。

XDocument xdoc = XDocument.Parse(
    @"<People>
         <Person>
             <Name>坂本竜馬</Name>
             <Age>35</Age>
         </Person>
      </People>");
var q = xdoc.Root.Descendants()
    .Where(e => e.Name == "Age")
    .Select(e => e.Value);
q.ToList().ForEach(Console.WriteLine);

検索対象が子孫要素なので、Age要素を取得できます。
  
Posted by gushwell at 22:19Comments(0)TrackBack(0)

2008年11月30日

XMLからDictionary型への変換

   このエントリーをはてなブックマークに追加 Clip to Evernote
<root>
   <key1>値1</key1>
   <key2>値2</key2>
   <key3>値3</key3>
   <key4>値4</key4>
</root>

といったXMLファイルに対して、以下のようなコードを書いた。
XDocument xdoc = XDocument.Load("sample.xml");
var query = from pair in xdoc.Root.Elements()
            select new {
                Key = pair.Name.ToString(),
                Value = int.Parse(pair.Value)
            };
var dict = query.ToDictionary<string,int>(
    (x => x.Key), (x => x.Value));
foreach (var d in dict) {
    Console.WriteLine(d.Key + "=" + d.Value);

XMLからDictionary型への変換をしているわけだ。
でも、ToDictionaryの箇所で、 「ジェネリックの第1型引数のTSourceが抜けている」のでエラーのなってしまう。
匿名クラスなんだから、ここで、型を書くわけにはいかないし...
ということは、匿名クラスじゃなくて、KeyValuePairを使えばいいんだな。
で、書いたコード。
XDocument xdoc = XDocument.Load("sample.xml");
var query = from xbook in xdoc.Root.Elements()
            select new KeyValuePair<string, int>(
                xbook.Name.ToString(), 
                int.Parse(xbook.Value));
var dict = query.ToDictionary<KeyValuePair<string,int>,string,int>(
    (x => x.Key), (x => x.Value));
foreach (var d in dict) {
    Console.WriteLine(d.Key + "=" + d.Value);

うーん、ToDictionaryが冗長すぎる。
でも、よくよく考えたら、ジェネリックメソッドの型推論には、匿名型もOKなんだから、

XDocument xdoc = XDocument.Load("sample.xml");
var query = from pair in xdoc.Root.Elements()
            select new {
                Key = pair.Name.ToString(),
                Value = int.Parse(pair.Value)
            };
var dict = query.ToDictionary(
    (x => x.Key), (x => x.Value));
foreach (var d in dict) {
    Console.WriteLine(d.Key + "=" + d.Value);

で良かった。
カギカッコが無くなってすっきりした。   
Posted by gushwell at 22:21Comments(2)TrackBack(1)

2008年10月31日

LINQ to XMLのハロウィーン問題

   このエントリーをはてなブックマークに追加 Clip to Evernote
宣言型コードと命令型コードの混在のバグ (C#) (LINQ to XML)
に、「ハロウィーン問題」と呼ばれる問題が載っている。

XMLの要素を反復処理するコードを LINQ を使用して記述する場合、
そのループ処理の中で、要素の追加や削除を行うと、意図どおりに動作しないというもの。

あれ、これって、通常のコレクションでも同じ問題があるんじゃないの。
と思って、以下のようなコードを書いてみた。

 var list = new List {
1,2,3,4,5,6,7
};
foreach (var i in list) {
list.Add(i);
}

これを実行してみたら、なんと、

「{System.Collections.ListDictionaryInternal}コレクションが変更されました。列挙操作は実行されない可能性があります。」

という例外が出る。
へー、そんなチェックをしていたんだ。普段こんなコードを書いたことが無いので、初めて知りました。
LINQ to XMLだと、例外が出ないんですね。

  
Posted by gushwell at 20:50Comments(2)TrackBack(0)

2008年10月29日

「LINQ to XML 軸」?

   このエントリーをはてなブックマークに追加 Clip to Evernote
LINQ to XML 軸

「軸」ってなんですか?
日本語としてものすごく違和感がある。
LINQ to XML Axesの略らしい。
調べたら、Axes は、 Axisの複数形。
確かに、しっくりくる訳をつけるのは難しいのかな。
でも、なんだかなー。
  
Posted by gushwell at 20:38Comments(0)TrackBack(0)

2008年02月20日

LINQ to XML その12−配列からの変換

   このエントリーをはてなブックマークに追加 Clip to Evernote
こんどは、前回の逆のコード

配列のデータを XMLに変換するコードです。
こちらも、LINQを使います。

 var x = new XElement("People",
from p in people
select
new XElement("Person",
new XAttribute("IsReal", p.IsReal),
new XElement("Name",p.Name),
new XElement("Age",p.Age)
)
);
x.Save("people.xml");


かなり簡潔に書けますね。
XElement のコンストラクタの第2引数に、クエリ式を書けるってのがミソですね。
これで、「エレメントオブジェクトを生成し、ノードに追加」っていう面倒なコードを書かずに済みます。

ちなみに、Person配列は、以下のようなデータです。

static Person[] people = {
new Person { Name="徳川家康", Age=35, IsReal=true },
new Person { Name="織田信長", Age=44, IsReal=true },
new Person { Name="明智小五郎", Age=39, IsReal=false },
new Person { Name="石田三成", Age=18, IsReal=true },
new Person { Name="明智光秀", Age=52, IsReal=true },
new Person { Name="両津勘吉", Age=40, IsReal=false },
};


Linq to XML その11

  
Posted by gushwell at 20:12Comments(0)TrackBack(0)

LINQ to XML その12−配列からの変換

   このエントリーをはてなブックマークに追加 Clip to Evernote
こんどは、前回の逆のコード

配列のデータを XMLに変換するコードです。
こちらも、LINQを使います。

 var x = new XElement("People",
from p in people
select
new XElement("Person",
new XAttribute("IsReal", p.IsReal),
new XElement("Name",p.Name),
new XElement("Age",p.Age)
)
);
x.Save("people.xml");


かなり簡潔に書けますね。
XElement のコンストラクタの第2引数に、クエリ式を書けるってのがミソですね。
これで、「エレメントオブジェクトを生成し、ノードに追加」っていう面倒なコードを書かずに済みます。

ちなみに、Person配列は、以下のようなデータです。

static Person[] people = {
new Person { Name="徳川家康", Age=35, IsReal=true },
new Person { Name="織田信長", Age=44, IsReal=true },
new Person { Name="明智小五郎", Age=39, IsReal=false },
new Person { Name="石田三成", Age=18, IsReal=true },
new Person { Name="明智光秀", Age=52, IsReal=true },
new Person { Name="両津勘吉", Age=40, IsReal=false },
};


Linq to XML その11

  
Posted by gushwell at 20:12Comments(0)TrackBack(0)

LINQ to XML その12−配列からの変換

   このエントリーをはてなブックマークに追加 Clip to Evernote
こんどは、前回の逆のコード

配列のデータを XMLに変換するコードです。
こちらも、LINQを使います。

 var x = new XElement("People",
from p in people
select
new XElement("Person",
new XAttribute("IsReal", p.IsReal),
new XElement("Name",p.Name),
new XElement("Age",p.Age)
)
);
x.Save("people.xml");


かなり簡潔に書けますね。
XElement のコンストラクタの第2引数に、クエリ式を書けるってのがミソですね。
これで、「エレメントオブジェクトを生成し、ノードに追加」っていう面倒なコードを書かずに済みます。

ちなみに、Person配列は、以下のようなデータです。

static Person[] people = {
new Person { Name="徳川家康", Age=35, IsReal=true },
new Person { Name="織田信長", Age=44, IsReal=true },
new Person { Name="明智小五郎", Age=39, IsReal=false },
new Person { Name="石田三成", Age=18, IsReal=true },
new Person { Name="明智光秀", Age=52, IsReal=true },
new Person { Name="両津勘吉", Age=40, IsReal=false },
};


Linq to XML その11

  
Posted by gushwell at 20:12Comments(0)TrackBack(0)