asp.net文章截取显示摘要 转
时间:2010-12-02 来源:ndxsdhy
小马http://blog.csdn.net/cngkqy
"
博客系统通常的做法是,在博客的首页只显示文章的摘要,点击标题进入以后查看全文。显示哪一部分作为摘要是个比较特殊的问题,不同的系统都有自己不同的处理方式,有的是将摘要和扩展部分作为两个输入框,由用户自己决定哪些部分作为摘要,而且上下两部分都是完整的HTML,不存在截取的问题,就像本站使用的Serendipity系统。还有一种像WordPress,你可以自己在正文区中插入一个<!--More-->的标记,显示博客列表页的时候,会对文章以这个标记进行截取。不过我没有试过在一个Table的中间插入这个标记会怎么样,不过这种做法也是完全让用户自主决定如何截取文章,即使截错了,用户重新设置一下就OK了。
而我们公司的博客系统在设计之初,被很多人的意见所左右,(主要是许多没有真正写过博客的人的意见),意见是使用两个框的方式太麻烦,插入标记大部分恐怕也搞不懂,我们要给用户提供最简单的操作,用户只要写他的文章,如何截取交给系统就可以了。由此,让我陷入了一个疯狂改Bug的循环。
从整段的HTML中截取400个字作为摘要,如何处理?也许删除所有<>标签是最简单的办法,但是,博客的文字大家还是想要保留个性,而且有人想使用大字体,或者想对某篇文章使用大字体,以便更加显著,等等诸如此类的需求。总之,用户只想让自己的博客更漂亮,才不会管你怎么截取。
如果只是简单的按照400个字来截取,那么很可能会截到一个标签的中间,这半个标签可能就会导致后面的大段文本被作为标签内文字而不显示,直到遇到下一个结束符为止。于是首先要根据<>标记符,确保要截取的位置不在这两个标记中间。具体的做法是,找到一个<符号,看看里面的标记,去找它所对应的末尾标记,比如找到<p,就去找</p>,找到<div,就去找</div>。随后又发现,如果截取了半个Table,整个页面的布局就会错位,博客的侧边栏都跑到正文的下面去了,因为被作为Table里面的单元格来处理了。想来想去,决定如果出现Table的话,就在Table之前截断,结果导致许多文章的摘要里一个字都没有。然后又发现,不止Table会破坏布局,如果div的前后不对应,布局也会错位,因为我们的博客模板使用的是Div布局。用前面的截取方法存在一个问题,因为Div是可以嵌套的,连续的两个<div><div>标记,就会出现遇到第一个div标记的时候,直接跳到了第一个结尾的</div>标记上去,结果第二个<div>就没有结束符了。除此之外,font, span等等都是可以嵌套的。
后来又想了个办法,干脆把所有的div, font, span全部过滤掉,所<p></p>全部换成br,终于,基本上不会出现截错的问题了,但是,许多文章的分段和缩进是在div里面使用style来定义的(不知道这些用户的文章是从哪里拷过来的),结果许多人的博客首页文字都变成了一样的12px文字,而且密密麻麻挤在一起,极其不美观。再后来,还是有个用户报怨自己博客页面出错,无法打开。进去一看,他的博客文章里居然有N多<!--[IF[之类的标记,出现这种符号以后,用来截取的正则表达式就会报错。于是又在截取之前将注释类符号全部删掉。过了两天,他又报错,原来文章里还有<
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Text.RegularExpressions;
using System.Text;
public class nb
{
/// <summary>
/// 提取摘要,是否清除HTML代码
/// </summary>
/// <param name="content"></param>
/// <param name="length"></param>
/// <param name="StripHTML"></param>
/// <returns></returns>
public static string GetContentSummary(string content, int length, bool StripHTML)
{
if (string.IsNullOrEmpty(content) || length == 0)
return "";
if (StripHTML)
{
Regex re = new Regex("<[^>]*>");
content = re.Replace(content, "");
content = content.Replace(" ", "").Replace(" ", "");
if (content.Length <= length)
return content;
else
return content.Substring(0, length) + "……";
}
else
{
if (content.Length <= length)
return content;
int pos = 0, npos = 0, size = 0;
bool firststop = false, notr = false, noli = false;
StringBuilder sb = new StringBuilder();
while (true)
{
if (pos >= content.Length)
break;
string cur = content.Substring(pos, 1);
if (cur == "<")
{
string next = content.Substring(pos + 1, 3).ToLower();
if (next.IndexOf("p") == 0 && next.IndexOf("pre") != 0)
{
npos = content.IndexOf(">", pos) + 1;
}
else if (next.IndexOf("/p") == 0 && next.IndexOf("/pr") != 0)
{
npos = content.IndexOf(">", pos) + 1;
if (size < length)
sb.Append("<br/>");
}
else if (next.IndexOf("br") == 0)
{
npos = content.IndexOf(">", pos) + 1;
if (size < length)
sb.Append("<br/>");
}
else if (next.IndexOf("img") == 0)
{
npos = content.IndexOf(">", pos) + 1;
if (size < length)
{
sb.Append(content.Substring(pos, npos - pos));
size += npos - pos + 1;
}
}
else if (next.IndexOf("li") == 0 || next.IndexOf("/li") == 0)
{
npos = content.IndexOf(">", pos) + 1;
if (size < length)
{
sb.Append(content.Substring(pos, npos - pos));
}
else
{
if (!noli && next.IndexOf("/li") == 0)
{
sb.Append(content.Substring(pos, npos - pos));
noli = true;
}
}
}
else if (next.IndexOf("tr") == 0 || next.IndexOf("/tr") == 0)
{
npos = content.IndexOf(">", pos) + 1;
if (size < length)
{
sb.Append(content.Substring(pos, npos - pos));
}
else
{
if (!notr && next.IndexOf("/tr") == 0)
{
sb.Append(content.Substring(pos, npos - pos));
notr = true;
}
}
}
else if (next.IndexOf("td") == 0 || next.IndexOf("/td") == 0)
{
npos = content.IndexOf(">", pos) + 1;
if (size < length)
{
sb.Append(content.Substring(pos, npos - pos));
}
else
{
if (!notr)
{
sb.Append(content.Substring(pos, npos - pos));
}
}
}
else
{
npos = content.IndexOf(">", pos) + 1;
sb.Append(content.Substring(pos, npos - pos));
}
if (npos <= pos)
npos = pos + 1;
pos = npos;
}
else
{
if (size < length)
{
sb.Append(cur);
size++;
}
else
{
if (!firststop)
{
sb.Append("……");
firststop = true;
}
}
pos++;
}
}
return sb.ToString();
}
}
}