さて、XML での LINQ でポイントのひとつになる XName
これはすばらしいんです。
LocalName と名前空間情報を格納します。
QName をイメージしてもらうとわかりやすいかもしれません。
QName を一括で扱えるクラスってこれまで無かったのですよ。(SoapQName 見たいなのはあるみたいですが、XML を処理する上でという話で)
これまではメソッドのオーバーロードで対応していたわけで、QName クラスがあればスマートなのになぁと何度も思ってました。
ま、DOM に則していたからそれはそれで当然なのですが。
で、この XName はインスタンス生成時には文字列で宣言すればいいのですが、ひとつポイントがあります。
それは展開された名前でないといけないということ。
下記のサンプル見てもらえたらわかりやすいでしょう。
<?xml version="1.0" encoding="UTF-8"?>
<ns:root xmlns:ns="urn:sample">
<ns:item key="11">1-1</ns:item>
<ns:item key="12">1-2</ns:item>
<ns:item key="13">1-3</ns:item>
<ns:item key="21">2-1</ns:item>
<ns:item key="22">2-2</ns:item>
<ns:item key="23">2-3</ns:item>
<ns:item key="31">3-1</ns:item>
<ns:item key="32">3-2</ns:item>
<ns:item key="33">3-3</ns:item>
</ns:root>
先のエントリの XML に名前空間を付けただけです。
コレに対する処理はこうやります。
XName key = "key";
XDocument doc = XDocument.Load(@"D:\temp\test.xml");
XElement documentElement = (XElement)doc.FirstNode;
IEnumerable<XElement> elements =
from child in documentElement.Elements("{urn:sample}item")
where item.Attribute(key).Value.EndsWith("1")
select item;
foreach (XElement elm in elements) {
Console.WriteLine(elm);
}
{urn:sample}item が展開された名前です。
名前空間接頭辞で扱うわけじゃないというところに注意です。
XML やってたら、展開された名前とはよく出てくる単語ですがなじみ無い人も多いでしょう。
名前空間接頭辞って変数みたいなもので、どんなプレフィクスがついていても実際は URI に所属しているということが理解していただけたら展開された名前で扱うことは至極当然ということがわかっていただけるでしょう。