为了将博客导入到blogengine,需要将别的网站的博客rss转化成blogengine支持的博客xml文件blogML。
     首先下载一个现成的blogML2.0生成源文件,包含两个文件,一个前台文件blogml.aspx,一个后台程序blogml.aspx.cs,从前台程序中看到主要结构是四个repeater控件:

1.<asp:Repeater id="tags" runat="server">

2.<asp:Repeater id="posts" OnItemDataBound="posts_ItemDataBound" runat="server">

3.<asp:Repeater id="postTags" runat="server">

4.<asp:Repeater id="comments" runat="server">

     第一个是显示分类的,第二个实现每条博文的显示,第三第四个是嵌套在第二个Repeater中的Repeater。

     后台程序就是实现这些Repeater控件的数据绑定,默认使用的数据是从数据库中提取,使用存储过程取得数据加入到dataset中,再将dataset绑定到Repeater上,实现数据罗列。

    而我们需要的数据源是从rss取得,看下需要转化的RSS文件,结构为rss/channel/item,每个item就是一条博文记录,里面有标题、发布时间、分类、tag、内容、评论等信息。评论节点comment下又有子节点,记录了评论的时间、作者、内容等信息。

   首先实现博文Repeater的绑定private void bindToPostRepeater(Repeater rpt),还是使用dataset作为绑定介质。首先创建dataset新表和xml文档,从xml文档中读出需要的rss数据装载到dataset表中,再绑定就OK了。思路很简单,但是对于没有一点技巧的新手来说完成这些还是查了不少资料,从头了解dataset,xml和Repeater的数据绑定原理。万事开头难,就是这个道理。

View Code
private void bindToPostRepeater(Repeater rpt)
    {
        DataSet ds1 
= new DataSet();
        DataTable dt1 
= new DataTable();
        XmlDocument xmldoc 
= new XmlDocument();
        xmldoc.Load(MapPath(
"wp2.xml"));
        dt1.TableName 
= "post";
       dt1.Columns.Add(
"originalID", Type.GetType("System.String"));
        dt1.Columns.Add(
"id", Type.GetType("System.String"));
        dt1.Columns.Add(
"title", Type.GetType("System.String"));
        dt1.Columns.Add(
"content", Type.GetType("System.String"));
        dt1.Columns.Add(
"datePublished",Type.GetType("System.DateTime"));
       
  XmlNode postroot = xmldoc.DocumentElement;
        
int i = 0;
        
foreach (XmlNode post in postroot.ChildNodes[0])
        {
           dt1.Rows.Add(xmldoc.GetElementsByTagName(
"title")[i].ParentNode.Attributes[0].Value.ToString(), System.Guid.NewGuid().ToString(), xmldoc.GetElementsByTagName("title")[i].ChildNodes[0].Value.ToString(), xmldoc.GetElementsByTagName("content:encoded")[i].ChildNodes[0].Value.ToString(), xmldoc.GetElementsByTagName("post_date")[i].ChildNodes[0].Value.ToString());        
            i 
= i + 1;          
        }
        ds1.Tables.Add(dt1);
        rpt.DataSource 
= ds1;
        rpt.DataBind();
    }

    第一步完成,接下来要绑定嵌套的Repeater,原理一样,但是如何在绑定大Repeater的时候同时绑定小Repeater是个问题,所幸Repeater中有一个protected void posts_ItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)的方法,就是在这里实现内嵌Repeater的绑定。

 

View Code
protected void posts_ItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
    {
        
// Return for none data items
    if(e.Item.DataItem == null)
        {
            
return;
        }    
        RepeaterItem item 
= e.Item;        
        
string originalID=((DataRowView)e.Item.DataItem).Row["originalID"].ToString();//
        bindToTagRepeater(item, "postTags", originalID);  //绑定TagRepeater,参数item是当前项,postTags是tag Repeater的名称,originalID是另外加在原始rss的ITEM的属性值,用来唯一标识item项。
        bindToCommentRepeater(item, "comments", originalID); //绑定CommentRepeater,原理同上。
    }

 

看了源RSS,发现item节点中没有标识这个item唯一性的标记,就想到为这个item节点添加id属性,以便在程序中确定这个唯一的id。为了添加这个属性,颇费了些周折,主要是对于xml实在是不甚了解,为了实现这个操作,了解了节点、属性及创建、修改、删除节点,读写xml document的知识点。创建方法如下:

 

 XmlDocument xmldoc = new XmlDocument();
        xmldoc.Load(MapPath(
"wp.xml"));

        XmlNodeList xmlnodelist 
= xmldoc.GetElementsByTagName("item");
        
for (int i = 0; i < xmlnodelist.Count; i++)
        {

            XmlAttribute xmlatt 
= xmldoc.CreateAttribute("id");
            xmlatt.Value 
= (i + 1).ToString();

            xmlnodelist.Item(i).Attributes.Append(xmlatt);          
        }
        xmldoc.Save(
"d:/project/repeater/wpaddid.xml");

其中wp.xml是原wp文件,注意原文件中的标记前有前缀wp:,可使用查找,替换去除再进行以下操作,添加了item的属性ID后将新xml文档保存在wpaddid.xml中,xmldoc.save后面的文件地址是绝对路径.

 

最后再通过xpath找到id为originalID的item项,绑定其中的tag和comment到tag Repeater和comment Repeater上。绑定原理同post Repeater。

 

View Code
private void bindToTagRepeater(RepeaterItem item, String rptName, string originalID)
    {
       
        Repeater rpt 
= (Repeater)item.FindControl(rptName);
      

        DataSet ds1 
= new DataSet();
        DataTable dt1 
= new DataTable();
        XmlDocument xmldoc 
= new XmlDocument();
        xmldoc.Load(MapPath(
"wp2.xml"));
        dt1.TableName 
= "postTags";
        dt1.Columns.Add(
"originalID", Type.GetType("System.String"));
        dt1.Columns.Add(
"content", Type.GetType("System.String"));
        XmlNodeList tagnodelist 
= xmldoc.SelectNodes("//item[@id='" + originalID + "']/child::category");
             
for (int i = 0; i < tagnodelist.Count; i++)
           {
            dt1.Rows.Add(originalID, tagnodelist[i].ChildNodes[
0].Value.ToString());
           }
        ds1.Tables.Add(dt1);
        rpt.DataSource 
= ds1;
        rpt.DataBind();
          }

 

 

 前台的数据绑定代码形同“"<%#DataBinder.Eval(Container.DataItem, "content")%>”,日期格式使用“<%#DataBinder.Eval(Container.DataItem, "datePublished", "{0:s}")%>”,发现一个小问题,原始的rss中的tag每条都是重复显示,要解决这个问题也可以借助Repeater的特性,一隔一显示,只需要在Repeater中添加:

<AlternatingItemTemplate>
</AlternatingItemTemplate>

里面什么也不填,显示的时候就会一隔一显示,就能达到需要的效果了,这是意外发现的,一般都是用这个改变隔行样式,没想到在这里派上大用场了:)

至此,rss转化成blogML基本成功,还没整体导入,待续。