試みに、RSSリーダーを作ってみた。

Windows Developer という雑誌の記事を参考にしました)

まず、RSS読むクラス

    public class CRssRead
    {
        private string mRssURL = string.Empty;
        private XmlDocument mXmlDoc = null;
        public List results = null;

        public CRssRead(string rssURL)
        {
            this.mRssURL = rssURL;
            this.mXmlDoc = new XmlDocument();
            this.mXmlDoc.Load(rssURL);
            this.results = this.getresults(this.mXmlDoc);
        }

        private List getresults(XmlDocument xmlDoc)
        {
            List ret = new List();
            //RSS XMLNS マネージャ設定
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
            nsmgr.AddNamespace("rss", "http://purl.org/rss/1.0/");
            nsmgr.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
            nsmgr.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");
            //nsmgr.AddNamespace("sy", "");
            
            //rdf:li コレクション作成
            XmlNodeList linodes = xmlDoc.SelectNodes("/rdf:RDF/rss:channel/rss:items/rdf:Seq/rdf:li", nsmgr);

            //items取得
            foreach (XmlNode node in linodes)
            {
                //resource属性がマッチするitemノード取得
                string strResource = node.Attributes["resource", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"].Value;

                XmlNode aboutItem = xmlDoc.SelectSingleNode("/rdf:RDF/rss:item[@rdf:about='" + strResource + "']", nsmgr);

                //item 項目取得
                if (aboutItem != null)
                {
                    XmlNode titleNode = aboutItem.SelectSingleNode("rss:title", nsmgr);
                    XmlNode linkUrkNode = aboutItem.SelectSingleNode("rss:link", nsmgr);
                    XmlNode dateNode = aboutItem.SelectSingleNode("dc:date", nsmgr);

                    string title = string.Empty;
                    string link = string.Empty;
                    string dat = string.Empty;

                    if (titleNode != null)
                    {
                        title = titleNode.InnerText;
                    }
                    if (linkUrkNode != null)
                    {
                        link = linkUrkNode.InnerText;
                    }
                    if (dateNode != null)
                    {
                        dat = dateNode.InnerText;
                    }

                    ret.Add(new CRSSReadResults(title, link, dat));
                }
            }
            return ret;
        }

    }



    public class CRSSReadResults
    {
        public Int64 mItemNo = 0;
        public string mTitle = string.Empty;
        public string mLinkURL = string.Empty;
        public DateTime mDate = new DateTime();

        public CRSSReadResults(string title, string linkURL, string date)
        {
            this.mTitle = title;
            this.mLinkURL = linkURL;
            this.mDate = fncRSSdatestr2csDate(date);
        }
        private DateTime fncRSSdatestr2csDate(string datestr)
        {
            char sep = new char { 'T', '+' };
            string newdatestr = datestr.Split(sep)[0].Replace( '-', '/');
            string newtimestr = datestr.Split(sep)[1];
            return Convert.ToDateTime( newdatestr + " " + newtimestr);
        }
    }

RSSで読んだホームページを、Oracleに保存した

まず、WebBrowserコンポーネントを少し改造

    public class rssWeb : WebBrowser
    {
        public CRSSReadResults item = null;
        public rssWeb(CRSSReadResults res)
        {
            this.item = res;
        }
    }

で、RSS読み込みをキックするやつ

        private void btnRssReadTest_Click(object sender, EventArgs e)
        {
            string rssUrl = "http://r.hatena.ne.jp/kabacsharp/rss";
            CRssRead rssDoc = new CRssRead(rssUrl);


            this.CRSS2DataBase(rssDoc);
        }

で、実際にRSSのURLを読み込む部分

        private void CRSS2DataBase(CRssRead rssDoc)
        {
            /*
            for (int i = 0; i < 3; i++)
            {
                this.openNewTab(rssDoc.results[i].mLinkURL);
            }
             */
            foreach (CRSSReadResults item in rssDoc.results)
            {
                //MessageBox.Show(item.mDate.ToString());
                DataTable tab = new ABCS_RSS_ITEMTableAdapter().GetDataBy(item.mLinkURL, item.mDate);

                //string ret = "ok";
                if (tab.Rows.Count == 0)
                {
                    //ret = "null";
                    object ret = new ABCS_RSS_ITEMTableAdapter().InsertQuery(item.mTitle, item.mLinkURL, item.mDate);
                    DataTable tab2 = new ABCS_RSS_ITEMTableAdapter().GetDataBy(item.mLinkURL, item.mDate);
                    item.mItemNo = Convert.ToInt64(tab2.Rows[0]["item#"]);
                }
                else
                {
                    //item.mItemNo = Convert.ToInt64(tab.Rows[0]["item#"]);
                    continue;
                }

                this.openRSSTab(item.mLinkURL, item);

                /*
                if (this.rssweb != null && this.rssweb.Document != null)
                {
                    foreach (HtmlElement el in this.rssweb.Document.All)
                    {
                        object obj = new ABCS_RSS_HTMLDOCTableAdapter().InsertQuery(el.TagName, el.InnerText, item.mItemNo);
                    }
                }
                 */
            }
            MessageBox.Show("ok");
        }

        public void rssWebLoadComplete(object sender, System.Windows.Forms.WebBrowserDocumentCompletedEventArgs e)
        {
            rssWeb web = sender as rssWeb;
            if (web != null)
            {
                if (web != null && web.Document != null)
                {
                    foreach (HtmlElement el in web.Document.All)
                    {
                        try
                        {
                            object obj = new ABCS_RSS_HTMLDOCTableAdapter().InsertQuery(el.TagName, el.InnerText, web.item.mItemNo);
                        }
                        catch (Exception excp)
                        {
                            string a = excp.ToString();
                        }
                    }
                }
            }
        }

上記、rssWebLoadCompleteは、WebBrowserコンポーネントのイベントにした。以下の様。

        private void openRSSTab(string url, CRSSReadResults res )
        {
            TabPage tab = this.rsstab;
            rssWeb web = new rssWeb( res );
            web.ScriptErrorsSuppressed = true;
            web.DocumentCompleted += rssWebLoadComplete; //イベント設定

            web.Dock = DockStyle.Fill;
            tab.Controls.Add(web);

            web.Navigate(url);

            while (web.IsBusy)
            {
                Application.DoEvents();
            }

            ContextMenuStrip topmenu = new ContextMenuStrip();
            ContextMenuStrip menu = web.ContextMenuStrip;

            web.ContextMenuStrip = topmenu;

            this.trace_.Nodes.Add(new TreeNode(url));

            //this.tabControl.Controls.Add(tab);
            this.tabControl.SelectTab(tab);
        }

イベントにした理由は、HTMLDocmentは、表示完了しないと取得できないため、
表示完了時に発行されるイベントメソッドの中で、HTMLDocumentを取得するようにしたため。

ドツボにはまったのは、web.IsBusy==true になっても、HTMLDocumentは取得できなかったこと(泣)


ちなみに、Oracleに用意したテーブルのDDLは以下の様

CREATE TABLE ABCS_ADMIN.ABCS_RSS_ITEM
(
    ITEM#                          NUMBER NOT NULL,
    TITLE                          VARCHAR2(4000),
    LINKURL                        VARCHAR2(4000),
    UPDATED                        DATE,
    CONSTRAINT SYS_C0014694 PRIMARY KEY (ITEM#) USING INDEX
)

CREATE TABLE ABCS_ADMIN.ABCS_RSS_HTMLDOC
(
    HTML#                          NUMBER NOT NULL,
    TAG                            VARCHAR2(100),
    INNERTEXT                      CLOB,
    ITEM#                          NUMBER,
    CONSTRAINT SYS_C0014695 PRIMARY KEY (HTML#) USING INDEX
    CONSTRAINT SYS_C0014696 FOREIGN KEY (ITEM#) REFERENCES ABCS_ADMIN.ABCS_RSS_ITEM (ITEM#)
)
LOB (INNERTEXT) STORE AS SYS_LOB0000074305C00003$$
(
    ENABLE STORAGE IN ROW
    CHUNK 8192
    NOCACHE
    LOGGING
    STORAGE( INITIAL 64K MINEXTENTS 1 MAXEXTENTS 2147483645 BUFFER_POOL DEFAULT )
    INDEX SYS_IL0000074305C00003$$
)