前回、更新通知に3つのフォーマットの系統があることを確認しました。とりあえず、ルート要素のローカル名を見れば、どの系統なのか判別できそうだとわかりました。次、配信されているものを取り出します。
さて、サンプルを見ると、次のようになっています。
static IEnumerable<XElement> GetItems() {
string[] feeds = {
"http://blogs.msdn.com/ericlippert/rss.aspx",
"http://blogs.msdn.com/wesdyer/rss.aspx",
"http://blogs.msdn.com/charlie/rss.aspx",
"http://blogs.msdn.com/cyrusn/rss.aspx",
"http://blogs.msdn.com/mattwar/rss.aspx",
"http://blogs.msdn.com/lucabol/rss.aspx",
"http://www.pluralsight.com/blogs/dbox/rss.aspx",
"http://blogs.msdn.com/jomo_fisher/rss.aspx"
};
foreach (var str in feeds) {
var feed = XDocument.Load(str);
var items = feed.Root.Element("channel").Elements("item");
foreach (var item in items)
yield return item;
}
}
肝心の所は、下の foreach
ブロック内にある、feed.Root.Element("channel")
のところです。ドキュメントを確認します。
XContainer.Element メソッド より
指定した XName の最初の子要素を (ドキュメント順に) 取得します。
つまり、feed
が示す XDocument インスタンスからルート要素を取り出し、ルート要素の "channel"
という名前のエレメントを取り出す、ということですね。
とりあえず、他のフォーマットでも大丈夫か確認するため、このコードの feed
を書き換え、実行します。試しに http://www.atmarkit.co.jp/aboutus/rss/rss.html から、RSS 1.0 のフォーマットを選んでみます。
例外が発生しました。NullReferenceException です。
デバッガで止めて、クイックウォッチを起動します。ここに feed. と入力すると、こんなところまでインテリセンスが働くのですね!続けて feed.Root.Element("channel") と入力します。すると、null が返ってきています。
データを確認します。ブラウザでアクセスし、ソースを表示します。抜粋します。
<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/modules/syndication/" xml:lang="ja">
<channel rdf:about="http://www.atmarkit.co.jp">
<title>@IT</title>
<link>http://www.atmarkit.co.jp</link>
<description>ITエンジニア対象の技術解説情報&コミュニティサイト</description>
<language>ja</language>
<dc:date>2009-06-08T03:00:13+09:00</dc:date>
<items>
ルート要素である RDF:rdf の直下に channel があります。なぜ取れないのでしょう?
ドキュメントを読み返し、いろいろいじっていると、feed.Root.Nodes() だと、アクセスできることがわかりました。ここから NodeType を見ると XElement となっています。Nodes メソッドが返す XNode インスタンスを XElement にキャストすると、キャストが成功しました。ここからアクセスすることにします。
/// <summary>
/// 指定されたエレメントに定義された、指定された名前を持つ最初のエレメントを取得します。
/// </summary>
/// <param name="rootElement">エレメントを探す元になるエレメント</param>
/// <param name="elementName">検索するエレメントのローカル名</param>
/// <returns>エレメントのノードから最初に見つかったエレメント</returns>
static public XElement GetElementFromNodes(XElement rootElement, string elementName) {
var nodes = rootElement.Nodes();
foreach (var node in nodes) {
if (node.NodeType == System.Xml.XmlNodeType.Element) {
XElement element = (XElement)node;
if (element.Name.LocalName == elementName) {
return element;
}
}
}
return null;
}
投稿日時 : 2009年6月8日 22:38