Blogengine.Netのブログロールの調整?

Blogengine.Netには、ブログロールというRSSリーダーともいうべき機能があり、ぶりちゃんも、ブログリンクとして、おもにPSUぶろぐなどで使用しています。

ただのリンクだけではなく、RSSを読み取って、最新の任意の件数を表示できるのは便利だと思います~

ただ、一部のブログシステムのRSSをうまく認識できないようです。
てっきり、ATOM関連が入ってるかなと思いましたが・・・まったくの検討はずれ(ぉい

まずは、コードをよーく見てみるために、どこにあるか探してみると・・・

App_Code/Controls/Blogroll.cs

にありました。

ここのProcessResposeメソッドで取得したRSSをチェック、それぞれのリストに入れているようですねぇ。

ぶりちゃんは、RSS 2.0のXML構造しか頭になかったので、このソースだとふつーにとおるなぁ・・・と思っていたのですが・・・
デバッグでRSSが読めないデータを追っていくと、構造が違う・・・
RSS 1.0の構造でした・・・^^;
タグの名称からして全く違うので、そりゃ認識するはずもないな^^;

いろいろ試行錯誤するにもうまくいかず・・・ネット上を探してみることに・・・

すると、C#でコードサンプルがあるじゃないですか・・・
(参考にしたブログはこちらです。)

ATOMは組み込んでいませんが、RSS1.0も読めるように、Blogrollを調整していきます。

App_Code/Controls/Blogroll.csの、ProcessResposeメソッドに、RSS1.0、2.0の判別を追加し、RSS 2.0なら既存の処理を、RSS 1.0の場合は新規に処理を追加しました。

尚、コードはあまりいい処理はしていないとおもいます^^;
参考にするも、そのまま貼り付けるにも・・・自己責任で~

        /// <summary>
        /// Gets the request and processes the response.
        /// </summary>
        private static void ProcessRespose(IAsyncResult async)
        {
            blogRequest blogReq = (blogRequest)async.AsyncState;
            try
            {
                using (HttpWebResponse response = (HttpWebResponse)blogReq.Request.EndGetResponse(async))
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(response.GetResponseStream());
                    XmlNodeList nodes;
                    if (GetRSSKind(doc) == "rdf:RDF")
                    {
                        //rss 1.0
                        XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
                        string ns = GetRSS1NameSpace(doc, "xmlns");
                        string nsrdf = GetRSS1NameSpace(doc, "xmlns:rdf");
                        nsmgr.AddNamespace("rdf", nsrdf);
                        nsmgr.AddNamespace("empty", ns);
                        nodes = doc.SelectNodes("rdf:RDF/empty:item", nsmgr);
                        foreach (XmlNode node in nodes)
                        {
                            string title = node.SelectSingleNode("empty:title", nsmgr).InnerText;
                            string link = node.SelectSingleNode("empty:link", nsmgr).InnerText;
                            DateTime date = DateTime.Now;
                            if (node.SelectSingleNode("empty:pubDate", nsmgr) != null)
                            {
                               date = DateTime.Parse(node.SelectSingleNode("empty:pubDate", nsmgr).InnerText);
                            }

                            blogReq.ItemTitles.Add(title);
                            blogReq.ItemLinks.Add(link);
                        }

                    }
                    else
                    {
                        //通常のrss 2.0用
                        nodes = doc.SelectNodes("rss/channel/item");
                        foreach (XmlNode node in nodes)
                        {
                            string title = node.SelectSingleNode("title").InnerText;
                            string link = node.SelectSingleNode("link").InnerText;
                            DateTime date = DateTime.Now;
                            if (node.SelectSingleNode("pubDate") != null)
                            {
                                date = DateTime.Parse(node.SelectSingleNode("pubDate").InnerText);
                            }

                            blogReq.ItemTitles.Add(title);
                            blogReq.ItemLinks.Add(link);
                        }
                    }
                }
            }
            catch
            {
            }
        }

 

RSS1.0の場合、rdf名前空間がありますので、通常のSelected(Single)Node(s)では取得できません。
XMLNamespaceManagerを作成し、必要な名前空間を指定する必要があるようです。
名前空間をXML内部から取得するためのメソッドや、RSSのバージョンを判別するメソッドはこのような感じに書いてみました。

        private static string GetRSSKind(XmlDocument xml)
        {
            foreach (XmlNode xmlNode in xml.ChildNodes)
            {
                if (xmlNode.Name == "rdf:RDF") return xmlNode.Name;
                if (xmlNode.Name == "rss") return xmlNode.Name;
            }
            return "";

        }
        private static string GetRSS1NameSpace(XmlDocument xml, string ns)
        {
            foreach (XmlNode xmlNode in xml.ChildNodes)
            {
                if (xmlNode.Name == "rdf:RDF") return xmlNode.Attributes.GetNamedItem(ns).InnerText;
            }
            return "";

        }

これは、ProcessResposeメソッドの後に追加しています。
これで、livedoorやfc2など、RSS1.0を使用しているブログでも、ブログロールで記事を正常に表示することができました^^

余談ですが・・・ProcessResposeメソッドでItem項目を取得する際、PubDateをチェックしていますが・・・チェックしているだけなのはなぜだろう(ぉ

上記の変更を反映したブログロールコントロールは以下よりダウンロードできます。
反映方法は、ファイル内のreadme_ja.txtをご覧ください。

公開終了

新バージョンをつくりましたので、そちらをおつかいくださいませ。
新バージョンの記事はこちら

コメントを書く

Month List