剖析CSDN论坛基于XML的回帖模式(转载)
CSDN采用的这样一种方法,发表帖子的时候先将回复的内容写入数据库,同时检查指定目录例如xmfiles下有没有帖子id为文件名的xml文件,如果没有,建立新的xml文件,写入帖子id,当前用户id,帖子标题,作者等一些信息,然后利用一个xslt将这个xml文件显示出来,需要指出的是xslt并不是只显示了帖子的内容,它在在其中包含了一个iframe,里面就是发表回复内容的表单,用户发表回复其实就是打开指定的xml文件,增加新的接点,然后保存,保存后直接刷新主xml文件即可,这样一来读帖子显示的时候就不用根据id从数据库里找帖子内容,然后再将数据读出来,而是只打开一个本地文件,并且解释样式的工作是利用xslt交给浏览器来解释,所以速度会快很多,也减轻了服务器的压力。原理基本上是这样,下面列出几个关键问题并附上代码:
1如何将帖子id传递给iframe中的表单
将id写进xml文件,利用xstl将id的值写进一个hidden,在iframe中的表单中利用document.all("topicid").value = top.document.all("topicid").value;读出,原因是有可能用户会同时读几篇文章,所以不能用session,而是采用这种方式来保存状态。
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type='text/xsl' href='message.xsl'?>
<replylist>
<topicid>251</topicid>
<author>yeqi</author>
<title>我爱你</title>
</replylist>
1如何将帖子id传递给iframe中的表单
将id写进xml文件,利用xstl将id的值写进一个hidden,在iframe中的表单中利用document.all("topicid").value = top.document.all("topicid").value;读出,原因是有可能用户会同时读几篇文章,所以不能用session,而是采用这种方式来保存状态。
2如何得到表单中的hidden的值
因为需要得到form里的值,所以在服务端处理前必须submit(),需要指出的是不能够在body onload里接受设置hidden的值,这样submit的值会是一个空值,而必须在提交窗体后执行段js取得hidden的值,接着马上submit!
3刷新xml文件的时候不能简单的用location.href=location.href之类的语句,而要用location.reload(),不然新增加的接点必须手动刷新后才能显示出来,原因是浏览器会认为是同一个文件,而输出的是缓存,csdn的做法是在location后面加一个变化的字符串,例如535.xml?temp=34557这样的形式,后面的34557是程序生成的一个随时间会变化的字符串,这样浏览器就会理解是不同的文件,而去重新载入。
4考虑浏览器对xml的支持
由于netscape等一些其他的浏览器对xml的支持不是很好,ie也只有5.5以上的版本才能很好的支持,所以必须检测浏览器,然后进行必要的服务器端转换!
1 showarticle.aspx接受请求的aspx页面:判断xml文件是否存在,浏览器类型等
1
using System;
2
using System.Collections;
3
using System.ComponentModel;
4
using System.Data;
5
using System.Drawing;
6
using System.Web;
7
using System.Web.SessionState;
8
using System.Web.UI;
9
using System.Web.UI.WebControls;
10
using System.Web.UI.HtmlControls;
11
using System.IO;
12
using Uptoec.Business ;
13
using Uptoec.Common ;
14
using Uptoec.DataAccess ;
15
using System.Data .SqlClient ;
16
using System.Xml.Xsl ;
17
using System.Xml ;
18
using System.Xml .XPath;
19
using System.Text ;
20
namespace ecArticle.BackWeb.test
21
{
22
/// <summary>
23
/// showarticlel 的摘要说明。
24
/// </summary>
25
public class showarticlel : System.Web.UI.Page
26
{
27
28
private string fileName;
29
private string id;
30
private string author;
31
private string postman;
32
private string title;
33
private string xsltFile;
34
private string xsltFile1;
35
private void InitializeComponent()
36
{
37
this.Load += new System.EventHandler(this.Page_Load);
38
39
}
40
41
42
private void Page_Load(object sender, System.EventArgs e)
43
{
44
//得到文章id
45
id =Request.QueryString ["id"].ToString ();
46
fileName ="xmlFiles\\" + id + ".xml";
47
fileName =System.Web .HttpContext.Current .Server .MapPath(fileName);
48
xsltFile = "xmlFiles\\message.xsl";
49
xsltFile =System.Web .HttpContext.Current .Server .MapPath(xsltFile);
50
51
xsltFile1 = "xmlFiles\\message1.xsl";
52
xsltFile1 =System.Web .HttpContext.Current .Server .MapPath(xsltFile1);
53
54
55
56
//得到用户名
57
postman =(string)Session["postman"];
58
59
//判断xml文件时候存在,否则创建xml文件
60
61
if(!File.Exists(fileName))
62
{
63
//创建xml文件;
64
65
FileStream fs =File.Create(fileName);
66
fs.Close ();
67
68
//从数据库得到文章的标题,作者,等一些信息
69
70
ArticleInfo article = new ArticleSystem().GetArticleById(Convert.ToInt32 (id));
71
author = article.Author ;
72
title = article.Title ;
73
74
XmlTextWriter writer = new XmlTextWriter((fileName), Encoding.UTF8);
75
76
//开始创建接点
77
writer.WriteStartDocument();
78
String PItext="type='text/xsl' href='message.xsl'";
79
writer.WriteProcessingInstruction("xml-stylesheet", PItext);
80
81
writer.WriteStartElement("replylist");
82
writer.WriteElementString("topicid",id);
83
writer.WriteElementString("author",author);
84
writer.WriteElementString("title",title);
85
writer.WriteEndElement();
86
writer.WriteEndDocument();
87
writer.Close ();
88
//结束建立xml文件
89
}
90
91
92
//检测浏览器是否支持xml
93
94
if(!(Convert.ToDouble(Request.Browser.Version)>=5.5))
95
{
96
XslTransform xslt = new XslTransform();
97
98
xslt.Load(xsltFile1);
99
XPathDocument xpathdocument = new
100
XPathDocument(fileName);
101
XmlTextWriter writer = new
102
XmlTextWriter(Response.OutputStream, Encoding.UTF8);
103
104
writer.Formatting=Formatting.Indented;
105
106
xslt.Transform(xpathdocument,null,writer,null);
107
108
}
109
else{
110
111
this.Response.Redirect ("xmlFiles/" + id + ".xml");
112
113
114
}
115
116
117
}
118
#region Web 窗体设计器生成的代码
119
override protected void OnInit(EventArgs e)
120
{
121
//
122
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
123
//
124
this.Load += new System.EventHandler(this.Page_Load);
125
base.OnInit(e);
126
}
127
128
/// <summary>
129
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
130
/// 此方法的内容。
131
/// </summary>
132
133
#endregion
134
}
135
}
136
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
2iframe中发表留言的post.aspx
1
using System;
2
using System.Collections;
3
using System.ComponentModel;
4
using System.Data;
5
using System.Drawing;
6
using System.Xml;
7
using System.Web;
8
using System.Web.SessionState;
9
using System.Web.UI;
10
using System.Web.UI.WebControls;
11
using System.Web.UI.HtmlControls;
12
13
namespace ecArticle.BackWeb.test
14
{
15
/// <summary>
16
/// xml 的摘要说明。
17
/// </summary>
18
public class xml : System.Web.UI.Page
19
{
20
protected System.Web.UI.WebControls.TextBox content;
21
protected System.Web.UI.HtmlControls.HtmlForm form1;
22
protected System.Web.UI.HtmlControls.HtmlInputButton Button1;
23
private string replytext;
24
private string postman;
25
private string id;
26
private string posttime;
27
private string xFileName;
28
private void Page_Load(object sender, System.EventArgs e)
29
30
{
31
32
33
}
34
35
#region Web 窗体设计器生成的代码
36
override protected void OnInit(EventArgs e)
37
{
38
//
39
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
40
//
41
InitializeComponent();
42
base.OnInit(e);
43
}
44
45
/// <summary>
46
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
47
/// 此方法的内容。
48
/// </summary>
49
private void InitializeComponent()
50
{
51
this.Button1.ServerClick += new System.EventHandler(this.Button1_ServerClick);
52
this.Load += new System.EventHandler(this.Page_Load);
53
54
}
55
#endregion
56
57
58
59
60
private void Button1_ServerClick(object sender, System.EventArgs e)
61
{
62
//需要根据hidden的值取得对应的xml文件名和作者的信息
63
id =Request.Form["topicid"];
64
xFileName = "xmlFiles/" + id + ".xml";
65
//得到用户信息
66
67
replytext=content.Text ;
68
posttime =System.DateTime .Now .ToLongTimeString();
69
70
string waittext ="正在生成静态页面,请稍后!";
71
//写入节点
72
Response.Write (waittext);
73
74
AddNode(xFileName,replytext,postman,posttime);
75
76
string ll ="<script language ='javascript'>top.location.reload()";
77
78
ll +="</script>";
79
Response.Write (ll);
80
81
82
83
84
}
85
86
87
88
89
private void AddNode(string xmlFile,string content,string postman,string ptime)
90
91
{
92
//将数据写入数据库
93
94
XmlDocument xmldoc = new XmlDocument ();
95
string filePath= System.Web .HttpContext.Current .Server.MapPath(xmlFile);
96
xmldoc.Load(filePath);
97
XmlNode root = xmldoc.DocumentElement ;
98
//开始创建新节点
99
100
XmlNode reply =xmldoc.CreateElement("reply");
101
102
XmlNode contentNode = xmldoc.CreateElement ("content");
103
104
XmlNode postmanNode = xmldoc.CreateElement ("postman");
105
106
XmlNode posttimeNode = xmldoc.CreateElement ("posttime");
107
//给各子节点赋值
108
contentNode.InnerXml="<![CDATA[" + content + "]]>";
109
postmanNode.InnerText = Session["postman"].ToString ();
110
posttimeNode .InnerText =ptime;
111
112
//将3个子节点添加到回复父节点
113
reply.AppendChild (contentNode);
114
reply.AppendChild (postmanNode);
115
reply.AppendChild (posttimeNode);
116
root.AppendChild(reply);
117
xmldoc.Save (filePath);
118
119
120
}
121
122
}
123
}/*生成随机数------
124
* -----------------------------------
125
Random rdm1 = new Random(unchecked((int)DateTime.Now.Ticks));
126
string r1 =rdm1.Next(10).ToString ();
127
Random rdm2 = new Random(rdm1.Next(10));
128
string r2= rdm2.Next(10).ToString ();
129
130
string time = System.DateTime.Now.ToShortTimeString();
131
time = time.Replace (":","");
132
string sec = System.DateTime.Now.Second.ToString ();
133
time =r1 + time + sec + r2;//生成随机数完毕--------------------------------------
134
string ll ="<script language ='javascript'>top.location.href='1.xml?temp=.";
135
*/
136
137
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
3 post.aspx的html代码
1
<%@ Page CodeBehind="post.aspx.cs" Language="c#" AutoEventWireup="false" Inherits="ecArticle.BackWeb.test.xml" %>
2
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
3
<HTML>
4
<HEAD>
5
<title>帮助</title>
6
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
7
<LINK href="style.css" type="text/css" rel="stylesheet">
8
<script language="javascript">
9
function sethidden()
10
{
11
12
document.all("topicid").value = top.document.all("topicid").value;
13
form1.submit();
14
15
}
16
</script>
17
</HEAD>
18
<body aLink="#000000" link="#000000" topMargin="2" ms_positioning="GridLayout">
19
<TABLE height="186" cellSpacing="0" cellPadding="0" width="378" border="0" ms_2d_layout="TRUE">
20
<TR vAlign="top">
21
<TD width="10" height="2"></TD>
22
<TD width="368"></TD>
23
</TR>
24
<TR vAlign="top">
25
<TD height="184"></TD>
26
<TD>
27
<TABLE height="183" cellSpacing="0" cellPadding="0" width="367" border="0">
28
<form id="form1" name="form1" method="post" runat="server">
29
<TBODY>
30
<tr>
31
<td align="left"></td>
32
</tr>
33
<tr>
34
<td align="left"></td>
35
</tr>
36
<tr>
37
<td align="left"><asp:textbox id="content" runat="server" Width="360px" Height="96px" EnableViewState="False"></asp:textbox></td>
38
</tr>
39
<tr>
40
<INPUT type="hidden" name="topicid">
41
<td><input id="Button1" onclick="sethidden();" type="button" value="我要疯了" runat="server" Text="提交查询内容">
42
</td>
43
</tr>
44
</TR>
45
</FORM></TABLE>
46
</TD></TR></TBODY></TD></TR></TBODY></FORM></TD></TR></TBODY></TABLE></TABLE></TABLE>
47
</body>
48
</HTML>
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
4 xml文件和xslt文件
1
<?xml version="1.0" encoding="utf-8"?>
2
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
3
4
<xsl:template match="/">
5
<html>
6
<title>AAAAA</title>
7
<body>
8
<h1><xsl:value-of select="replylist/topicid"/></h1>
9
<h1><xsl:value-of select="replylist/title"/></h1>
10
<h1><xsl:value-of select="replylist/author"/></h1>
11
<table width="75%" height="85" border="0" align="center" cellpadding="0" cellspacing="1" bgcolor="#333333">
12
<tr>
13
<td height="20" bgcolor="#FFFFFF">name</td>
14
<td align="right" bgcolor="#FFFFFF">posttime</td>
15
</tr>
16
<xsl:apply-templates select="replylist/reply">
17
</xsl:apply-templates>
18
</table>
19
<xsl:element name="input">
20
<xsl:attribute name="type">hidden</xsl:attribute>
21
<xsl:attribute name="name">topicid</xsl:attribute>
22
<xsl:attribute name="value"><xsl:value-of select="replylist/topicid"/></xsl:attribute>
23
</xsl:element>
24
25
<iframe name="post" src="../post.aspx" scrolling="no" MARGINHEIGHT="0" width="75%" MARGINWIDTH="0" FRAMESPACING="0" align="center" height="500" FRAMEBORDER="0"/>
26
</body>
27
</html>
28
</xsl:template>
29
30
<xsl:template match="reply">
31
<tr>
32
<td height="20" bgcolor="#FFFFFF">
33
<xsl:value-of select="postman"/>
34
</td>
35
<td align="right" bgcolor="#FFFFFF">
36
<xsl:value-of select="posttime"/>
37
</td>
38
</tr>
39
<tr bgcolor="#FFFFFF">
40
<td height="41" colspan="2">
41
<xsl:value-of select="content"/>
42
</td>
43
</tr>
44
</xsl:template>
45
</xsl:stylesheet>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
浙公网安备 33010602011771号