长文章自动分页

應燁軍 2009-11-09 01:49:32
1、问题:根据指定每页字符数,实现长篇文章自动分页(文章中包含大量的Html标记).

2、要求:

1)文章Html标记先过滤只保留<br>、<p>、<img>标记.

2)分页后尽量不破坏余下的标记结构.

3)每页字符数可以有误差.

4) 分页效率尽量高

请写出主要实现代码,或者提供一个详细的思路,谢谢!!。

附:两个正则

string allHtml= @"<[^>]*>";//匹配所有Html
string partHtml= @"<(?!br|\/?p|img)[^>]*>";//部分Html不匹配


...全文
668 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
haby0215 2010-08-11
  • 打赏
  • 举报
回复
楼主现在解决了吗?能共享下嘛,我现在正在这方面的知识呢,急求!
LYC_CLY 2010-06-18
  • 打赏
  • 举报
回复
literal 学习中
應燁軍 2009-11-09
  • 打赏
  • 举报
回复
谢谢大家的回答...
wuyq11 2009-11-09
  • 打赏
  • 举报
回复
这是一对多的设计.
在添加时,想分多少页,就添加多少次.
或添加文章时,通过标识符分页或按照分页添加文章内容,参考IWMS
或public string NoHTML(string Htmlstring) //去除HTML标记
{
Htmlstring = Regex.Replace(Htmlstring, @" ]*?>.*? ", "", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @" <(.[^>]*)>", "", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase);
Htmlstring = Regex.Replace(Htmlstring, @"-->", "", RegexOptions.IgnoreCase);
}
在分页
http://topic.csdn.net/u/20090321/15/0c1167e6-b829-4cf7-bfc3-a59f8211dd18.html
http://topic.csdn.net/u/20081205/13/874f3dcf-bae0-40b3-acd5-8d474edc24e8.html
skyland84 2009-11-09
  • 打赏
  • 举报
回复
想法说说:

先找出所有 你要保留的标志 并替换成自定义标志如:<img >=>[img src="..."]

之后替换所有的 html 标志为一个 分隔符:如[spliter]

然后 根据分隔符 拆分 成段 保存成string[]

遍历string[]
假设一页的字符 大概为400个字符
list<string> pagerlst=new ...
pageContent="";

for...
if(pageContent.length<400)
pageContent+=string[i]
else{
pagerlst.add(pagerContent);
pagerContent=string[i];
}

最后得到的 pagerlst.length就是分页数

在根据创建分页

希望对你有帮助





DemonAngle 2009-11-09
  • 打赏
  • 举报
回复
哈,这个只能帮忙顶了
闲游四疯 2009-11-09
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 poorchild 的回复:]
首先,多谢#19楼回答,你的方案做起来比较简单 。但也存在一些问题 :

1、你是以 <P>标记分段 要是我的文章没段落标记(如:文章要是从Word里面直接复制出来,基本都是div没什么 <p>标记)

2、分页性能上的问题
[/Quote]
忘记了 自己做习惯了 还以为你跟我一样是用文本编辑器的。。

1、要求文本比较规范点 html标记不能太杂太多
我这边说了 要规范点 所以发布的文章可能后台都还得自己稍微编辑下 分段下。。

性能问题的话。。不知道 。。 我自己做的时候 没啥感觉 因为只是分页 没有什么复杂的处理
性能还好吧。。

- - ! 嗨

jenny0810 2009-11-09
  • 打赏
  • 举报
回复
学习
應燁軍 2009-11-09
  • 打赏
  • 举报
回复


首先,多谢#19楼回答,你的方案做起来比较简单 。但也存在一些问题 :

1、你是以<P>标记分段 要是我的文章没段落标记(如:文章要是从Word里面直接复制出来,基本都是div没什么<p>标记)

2、分页性能上的问题
闲游四疯 2009-11-09
  • 打赏
  • 举报
回复
我只讲思路 楼主可以参考下啊。。
过滤就不说了 楼主自己搜正则匹配过滤。
文章分页想精确的话 就只能编辑的时候自己插入分页符 用程序是不可能得到满意的效果的。毕竟夹杂着
html标记 说不定还有图片之类的。。
如果大概匹配,我是按段落分。就是 <p> 跟 <br> , 这样不会把html标记截一半之类的
首先 过滤掉大部份无用的标记 如 span font, 将 br 换成 p
然后split 分组 p 标签的段落 得到数组
设置一个数值 当做每页字数 如 1000
开始拼接内容 字符串+=数组[i] 看得懂吧?
判断 当前字符串+数组[i]是不是大于上面那个数组 1000
如果 > 的话 拼接完这个数组[i] 就完了
如果 < 的话 继续拼接下个数组[i]
第二页内容就从第一页拼接的下个数组开始拼接,以此类推。

缺点:
1、要求文本比较规范点 html标记不能太杂太多
2、段落不能太长 不然误差长度会很大 - -!

只是我的一个实现思路 后面也失败了。。正则过滤不好处理。。
思路很简单 实现很麻烦。。楼主自己慢慢考虑。。
happy664618843 2009-11-09
  • 打赏
  • 举报
回复
不好搞啊 友情帮顶
應燁軍 2009-11-09
  • 打赏
  • 举报
回复
怎么没人了啊,各位大大帮帮忙..
應燁軍 2009-11-09
  • 打赏
  • 举报
回复
这是我手动分页代码!代码比较乱
调用方法

Web上放个
<asp:Literal ID="LiteralHtml" runat="server"></asp:Literal>
调用页面后台
  ArticlePaing articlePaging = new ArticlePaing();
LiteralHtml.Text = articlePaging.CoustomPaging("未分页的文章");




#region "Using"

using System;
using System.Text;
using System.Web;
using System.Web.Caching;

#endregion

namespace Teleware.Modules.Articles {

/// <summary>
/// 文章内容分页类
/// </summary>
public class ArticlePaing {

#region "Constructor"

/// <summary>
/// 构造函数初始一些默认值
/// </summary>
public ArticlePaing() {
ResetCache();
PageNumber = 1;
SelectPageStyle = "style='color:red'";
PageSize = 10;

}
#endregion

#region "Properties"

/// <summary>
/// 分页分隔标记
/// </summary>
public const string SpiltPageTag = "#Page#";
/// <summary>
/// 分页后连接和内容部分模板
/// </summary>
public const string PagingTemplate = @"<table width='100%' >

<tr><td style='height:300px' valign='top'>#Content#</td></tr>

<tr><td align='center'>#NavigatorUrl#</td></tr>

</table>";

/// <summary>
/// 文章内容缓存Key
/// </summary>
private const string ContentCacheKey = "ContentCacheKey";
/// <summary>
/// 页面大小|自动分页时指每页字符数
/// </summary>
public int PageSize { get; set; }
/// <summary>
/// 总记录数
/// </summary>
public int TotalCount { get; set; }
/// <summary>
/// 页号
/// </summary>
public int PageNumber { get; set; }
/// <summary>
/// 页数
/// </summary>
public int PageCount { get; set; }
/// <summary>
/// 选择页面样式
/// </summary>
public string SelectPageStyle { get; set; }

#endregion

#region "Public Method"

public string CoustomPaging(string content) {

TotalCount = GetPages(content).Length;
//计算出总页数
PageCount = TotalCount % PageSize == 0 ? TotalCount / PageSize : TotalCount / PageSize + 1;

string articlePage = HttpContext.Current.Request["ArticlePage"];

string isLeave = HttpContext.Current.Request["IsLeft"];

//分页模板,主要是用于分页内容和分页链接的布局

string template = PagingTemplate;

if (!string.IsNullOrEmpty(articlePage)) {
PageNumber = int.Parse(articlePage);
}
if (PageNumber > TotalCount) {
PageNumber = TotalCount;
}
if (PageNumber != -1 && PageNumber < 1) {
PageNumber = 1;
}
//如果余下参数不为空直接返回当前页余下的所有文章内容
if (isLeave != null) {
return template.Replace("#Content#", GetLeavePage(content)).Replace("#NavigatorUrl#", "");
}
return template.Replace("#Content#", GetPages(content)[PageNumber - 1]).Replace("#NavigatorUrl#", CreateNavigatorUrl(content));
}

#endregion

#region "Private Method"

/// <summary>
/// 获取所有页面数据(并将数据缓存)
/// </summary>
/// <param name="content"></param>
/// <returns></returns>
private string[] GetPages(string content) {

Cache cache = HttpContext.Current.Cache;
if (cache[ContentCacheKey] == null) {
string[] Pages = content.Split(new string[] { SpiltPageTag }, StringSplitOptions.RemoveEmptyEntries);
cache[ContentCacheKey] = Pages;
return Pages;
} else {
return cache[ContentCacheKey] as string[];
}
}

/// <summary>
/// 获取页面跳转的Url
/// </summary>
/// <param name="content">文章内容</param>
/// <returns></returns>
private string CreateNavigatorUrl(string content) {
StringBuilder sb = new StringBuilder();

//计算出当前文章所在页,已经取出所在组开始索引和结束索引
int start = 0, end = 0;
for (int j = 0; j < PageCount; j++) {
//判断文章所在页区间
if (PageNumber > j * PageSize && PageNumber <= (j + 1) * PageSize) {

start = j * PageSize;
//如果是最后一页,结束索引则等于总记录数
if (j == PageCount - 1) {
end = TotalCount;
} else {
end = (j + 1) * PageSize;
}
}
}

//上一页
if (PageNumber > 1) {
sb.Append(GetPreviousUrl());
}
//中间部分
for (; start < end; start++) {

//设置选中样式
if (PageNumber == start + 1) {

sb.Append(GetAppointUrl(start + 1, SelectPageStyle));
} else {

sb.Append(GetAppointUrl(start + 1, string.Empty));
}
}
if (PageNumber < TotalCount) {
//下一页
sb.Append(GetNextUrl());
//剩下所有页
sb.Append(GetLeaveUrl());
}

return sb.ToString();
}

/// <summary>
/// 生成链接Url
/// </summary>
/// <param name="arg1">参数</param>
/// <param name="strShow">链接显示的文字</param>
private string CreateLink(object url, string style, string strShow) {
return string.Format(" <a href='{0}' {1} > {2} </a>", url, style, strShow);
}

/// <summary>
/// 获取下页链接
/// </summary>
private string GetNextUrl() {
return CreateLink(string.Format("{0}&ArticlePage={1}", GetFirstRequestUrl(), PageNumber + 1), string.Empty, "下一页");
}

/// <summary>
/// 获取上页链接
/// </summary>
private string GetPreviousUrl() {
return CreateLink(string.Format("{0}&ArticlePage={1}", GetFirstRequestUrl(), PageNumber - 1), string.Empty, "上一页");
}

/// <summary>
/// 获取余下页链接
/// </summary>
private string GetLeaveUrl() {
return CreateLink(string.Format("{0}&ArticlePage={1}&IsLeft=true", GetFirstRequestUrl(), PageNumber), string.Empty, "余下页");
}

/// <summary>
/// 获取指定页链接
/// </summary>
/// <param name="PageNumber">页号</param>
/// <param name="selectStyle">链接样式</param>
private string GetAppointUrl(int PageNumber, string selectStyle) {
return CreateLink(string.Format("{0}&ArticlePage={1}", GetFirstRequestUrl(), PageNumber), selectStyle, "[" + PageNumber + "]");
}

/// <summary>
/// 获取从当前页开始剩下的所有页面
/// </summary>
/// <param name="content"></param>
/// <param name="PageNumer"></param>
/// <returns></returns>
private string GetLeavePage(string content) {

StringBuilder sb = new StringBuilder();
for (int i = PageNumber; i < GetPages(content).Length; i++) {
sb.Append(GetPages(content)[i]);
}
return sb.ToString();
}

/// <summary>
/// 如果请求地址无页分页参数,则清空缓存
/// </summary>
private void ResetCache() {
if (HttpContext.Current.Request.Url.ToString().IndexOf("&ArticlePage=") == -1) {
Cache cache = HttpContext.Current.Cache;
if (cache[ContentCacheKey] != null) {
cache.Remove(ContentCacheKey);
}
}
}
/// <summary>
/// 获取第一请求连接
/// </summary>
/// <returns></returns>
private string GetFirstRequestUrl() {
string url = HttpContext.Current.Request.Url.ToString();
if (url.IndexOf("&ArticlePage=") != -1) {
url = url.Substring(0, url.IndexOf("&ArticlePage="));
}
return url;
}

#endregion
}
}
nosuchtracter 2009-11-09
  • 打赏
  • 举报
回复
自动的确实不好用
容易出乱码,或者破坏页面
对文章进行循环,根据字节来算,判断某个字是英文还是汉字,这样来取长度
harvesthouhao 2009-11-09
  • 打赏
  • 举报
回复
你看一下TRUBO CMS ,他是这样做的,当编辑们人为文章过长时,可以在编辑器底下点击新建一页标签,然后继续增加文章下半部分。
shankaipingo 2009-11-09
  • 打赏
  • 举报
回复
关注
應燁軍 2009-11-09
  • 打赏
  • 举报
回复
手动分页代码我整理下.一会贴上来
ljb0502 2009-11-09
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 poorchild 的回复:]
手动插入分页符的我已经完成了,现在还差个自动的!
[/Quote]

手动的给贴份代码吧,自动的我也在搞,跟你的问题一样 结构都被破坏了
應燁軍 2009-11-09
  • 打赏
  • 举报
回复
谢谢各位的意见...

自动分页主要是为了用户考虑的,真正用户在使用长文章分页功能的时候没人会去手动分页,手动分页太累!

一篇文章放10多个标记,还要自己去找段落.想想都麻烦...

但是为了功能的完整性手动自动都得做...
zning8191 2009-11-09
  • 打赏
  • 举报
回复
在考验CSDN中的朋友们啊!
不过现在CSDN的质量正在下降啊!
加载更多回复(8)

62,050

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧