試みに、RSSリーダーを作ってみた。
(Windows Developer という雑誌の記事を参考にしました)
まず、RSS読むクラス
public class CRssRead { private string mRssURL = string.Empty; private XmlDocument mXmlDoc = null; public Listresults = 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); } }
まず、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は取得できなかったこと(泣)
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$$ )