試みに、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);
}
}
まず、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$$ )