带html标签的中英文字符串截取之完整性

需求一:

数据库中存储有一段带html标签的文字,如:

<P>《Windows》系统是越用越慢,这是不争的事实。</P> <P>因此,使用Win<font size='12pt'>d</font>ows就免不<img src='http:/www.blueidea.com/img/common/logo.gif'/>了要重新安装系统。<br>当然<span style='border:solid 1px red;font-size:23px'>,重新安装系</span>统并不难,但是安装完系统后你知道我<h1>们</h1>有多少事情必须要做吗?<br><strong>这</strong>可容不得丝毫的松懈,一旦马虎,将可能会导致前功尽弃,甚至有可能会造成数据丢失、信息泄密!</P>

现在要把它的前n个实际意义(即不包括html标签)的字符取出来,而且不能破坏它的段落标记,也就是说该是几段还是几段,p标签不算做n个字之内,又不能去掉

常见处:

新闻、小说、博客等的首页列表

代码:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HtmlTagRemove {
/**
* @function 出入口函数,获取文章的导读(前段文字)
* @param str 文章字符串
* @param length 导读长度
* @return 文章导读
*/
public String getNevigation(String str,int length){

//去掉除p以外的其他html标签
str = removeHtmlTagExceptP(str);

//获取导读
str = getHeadSubStr(str, length);

//补充导读中的P标签
str = repairPTag(str);

return str;
}

/**
* 函数说明:去掉p以外的其他标签
* @param 带html标签的字符串
* @return 处理后的字符串
*/
public String removeHtmlTagExceptP(String htmlstr) {
//正则说明:\s 空白字符, . 任何字符, * 零次或多次, ? 一次或一次也没有 ,*? 零次或多次 ,^ 除 之外

//Pattern pat = Pattern.compile("\\s">\\s*<[^p].*?[^p]>\\s*", Pattern.DOTALL | Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
Pattern pat = Pattern.compile("\\s">\\s*</?+[^p].*?>\\s*", Pattern.DOTALL | Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);

//\\s?[s|Sc|Cr|Ri|Ip|Pt|T]
Matcher m = pat.matcher(htmlstr);
//去掉所有html标记
String rs = m.replaceAll("");
rs = rs.replaceAll("&nbsp", " ");
rs = rs.replaceAll("<", "<");
rs = rs.replaceAll(">", ">");
return rs;
}
/**
* 函数说明:获取字符串的前一段文字
* @param str 目标字符串
* @param subLen 获取文字的长度
* @return 得到的字符串
*/
public String getHeadSubStr(String str,int subLen){
StringBuffer strBuffer =new StringBuffer();
int count=0;
for(int i=0;str!=null&&i<str.length();){
char c = str.charAt(i);
if(c=='<'&&str.charAt(i+1)=='p'&&str.charAt(i+2)=='>'){


strBuffer.append(c);
strBuffer.append(str.charAt(i+1));
strBuffer.append(str.charAt(i+2));
i+=3;
continue;
}
if(c=='<'&&str.charAt(i+1)=='/'&&str.charAt(i+2)=='p'&&str.charAt(i+3)=='>'){

strBuffer.append(c);
strBuffer.append(str.charAt(i+1));
strBuffer.append(str.charAt(i+2));
strBuffer.append(str.charAt(i+3));
i+=4;
continue;
}
strBuffer.append(c);
i++;
if(++count==subLen){
break;
}
}
return strBuffer.toString();
}
/**
* 方法说明:修补获取的字符串(主要是匹配p标签)
* @param str 目标字符串
* @return 修补后的字符串
*/
public String repairPTag(String str){

//判断截取的字符串p标签是否完整
String lastSubStr = str.substring(str.length()-3);
if(!lastSubStr.equals("</p>")){
str = str+"</p>";
}
return str;
}
}



需求二:数据库中存储一段带有html标签的文字,要从中取出前n个字符,且需保证一:html标签完整,不能出现如:<img hre后面被截断的情况,二:标签匹配 不允许出现如:<font ...>而不存在后面的</font>


import java.util.Stack;

public class StringHTML
{
public static void main(String[] args)
{
StringHTML stringHTML = new StringHTML();
String str = "<P>《Windows》系统是越用越慢,这是不争的事实。</P> <P>因此,使用Win<font size='12pt'>d</font>ows就免不<img src='http:/www.blueidea.com/img/common/logo.gif'/>了要重新安装系统。<br>当然<span style='border:solid 1px red;font-size:23px'>,重新安装系</span>统并不难,但是安装完系统后你知道我<h1>们</h1>有多少事情必须要做吗?<br><strong>这</strong>可容不得丝毫的松懈,一旦马虎,将可能会导致前功尽弃,甚至有可能会造成数据丢失、信息泄密!</P>";
System.out.println("str=" + str);
System.out.println("str=" + stringHTML.subHtmlStr(str, 10));
System.out.println("str=" + stringHTML.subHtmlStr(str, 20));
System.out.println("str=" + stringHTML.subHtmlStr(str, 30));
System.out.println("str=" + stringHTML.subHtmlStr(str, 50));
}

/**
* 方法说明:出入口函数,获取html标签完整的导读 参数说明:str 目标字符串 参数说明:leng 导读的长度 返回值: html标签完整的字符串
*/
public String subHtmlStr(String str, int length)
{
Stack<Character> charStack = new Stack<Character>(); //定义存储字符的栈
Stack<String> stringStack = new Stack<String>(); //定义存储字符串的栈
str = getNavigWithCorrectTag(str, length, charStack);
str = repairNavigition(str, stringStack);
return str;
}

/**
* @function 获取导读,保证标签不被破坏
* @param str 目标字符串
* @param length 导读的长度
* @return 标签不被破坏的字符串
*/
//保证标签的正确
public String getNavigWithCorrectTag(String str, int length, Stack<Character> charStack)
{
StringBuffer strBuffer = new StringBuffer();
int count = 0; //统计取到的字符数
for (int i = 0; str != null; i++)
{
char c = str.charAt(i);
if (c == '<')
{
//入栈操作
charStack.push(c);
}
if (c == '>')
{
//出栈操作
charStack.pop();
}
strBuffer.append(c);
if (c > 126 || c < 33)
{
count += 2;
}
else
{
count += 1;
}
if (i >= str.length())
{
break;
}
else
{
if (count >= length)
{
//空栈时
if (charStack.isEmpty())
{
break;
}
}
}
}
return strBuffer.toString();
}

/**
* @function 进一步匹配标签
* @param str 目标字符串
* @return 匹配好标签的字符串
*/
public String repairNavigition(String str, Stack<String> stringStack)
{
//初始化字符串栈
StringBuffer strBuffer = new StringBuffer();
for (int i = 0; str != null && i < str.length();)
{
char c = str.charAt(i);
//逐个获取html标签
if (c == '<')
{
String tempStr = "";
tempStr = tempStr + c;
while (true)
{
i = i + 1;
tempStr += str.charAt(i);
if (str.charAt(i) == '>')
{
i++;
break;
}
}
if (!(tempStr.equalsIgnoreCase("<br>") || tempStr.equalsIgnoreCase("<hr>")))
{
//非br\hr标签时
if (!(tempStr.contains("</")) && !tempStr.contains("/>"))
{
//起始标签时入栈
stringStack.push(tempStr);
//存储
strBuffer.append(tempStr);
}
else
{
//结束标签时,取栈顶元素
String startTag = stringStack.peek();
//取出temStr的2至length-1子串并判断是否匹配,看是否包含在栈顶元素中,若包含则匹配
if (startTag.contains(tempStr.substring(2, tempStr.length() - 1)))
{
//匹配时出栈
stringStack.pop();
strBuffer.append(tempStr);
}
else
{
//不匹配时说明当前标签是个单标签,直接加入
strBuffer.append(tempStr);
}
}
}
else
{
//br hr 标签直接加入
strBuffer.append(tempStr);
}
}
else
{
//普通字符时直接加入
strBuffer.append(str.charAt(i++));
}
}
//当栈不为空时,说明有未匹配的标签
while (!stringStack.isEmpty())
{
//取栈顶
String startTag = stringStack.peek();
//构造与之对应的结束标签
for (int j = 0; j < startTag.length(); j++)
{
if (startTag.charAt(j) != ' ' && startTag.charAt(j) != '>')
{
strBuffer.append(startTag.charAt(j));
}
else
{
break;
}
}
strBuffer.append("/>");
//栈顶元素出栈
stringStack.pop();
}
return strBuffer.toString();
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值