首页 / 网页编程 / ASP.NET / 安全的截取指定长度的html或者ubb字符串
        
            安全的截取指定长度的html或者ubb字符串2011-08-06 博客园 玉开在将html代码输出到页面时,有时候会需要截断字符串保留指定长度的字符串,由于html中有些标签 必须成对出现,所以在截取html时需要特别注意,不能因为截断问题把页面搞乱掉。在截取字符串时需要记录每一个标签是否关闭,如果截取到指定长度还有没有关闭的标签,那么我们 需要将标签关闭,或者删除掉未关闭的标签。不考虑某些不需要关闭标签的情况,html开始和结束标签总 是成对出现的,我们可以遍历输入的字符串,并在标签开始时放入堆栈中,遇到结束标签时从堆栈中弹出 一个元素,这样遍历到指定长度,堆栈中留下的标签就是需要补全或者删除掉的标签。下面是代码实现,如果大家有更好的方法请给出来:001 static char END_SLASH = "/";
002
003 /// <summary>
004  /// 安全的截断字符串
005 /// </summary>
006 /// <param  name="input">输入串</param>
007 /// <param name="length">截断长度 </param>
008 /// <param name="trimHalfTag">true:截断半截标签;false:补全 半截标签</param>
009 /// <param name="tagStartChar">标签开始字符 </param>
010 /// <param name="tagEndChar">标签结束字符 </param>
011 /// <param name="mustCloseTags">需要关闭的标签数组 </param>
012 /// <returns>length长度的字符串</returns>
013 public  static string SafeTrim(string input, int length, bool trimHalfTag, char  tagStartChar, char tagEndChar, string[] mustCloseTags)
014 {
015     if  (length <= 0) throw new ArgumentException("length 必须是正数");
016     if  (mustCloseTags == null) throw new ArgumentNullException ("mustCloseTags");
017
018     int inputLen = input.Length;
019     if  (string.IsNullOrEmpty(input) || inputLen <= length) return input;
020
021      string result = string.Empty;
022
023     //声明堆栈用来放标签
024      Stack<string> tags = new Stack<string>();
025
026      for (int i = 0; i < length; i++)
027     {
028         char  c = input[i];
029
030         if (c == tagStartChar)
031          {
032             string tag = string.Empty;
033              int tagIndex = i + 1;
034             bool isTagEnd =  false;
035             bool isTagNameEnd = false;
036              result += c;
037             bool hasMarkTagInStack =  false;
038             while (tagIndex < inputLen)
039              {
040                 char tagC = input [tagIndex];
041                 result += tagC;
042                  tagIndex++;
043                 if (tag ==  string.Empty && tagC == END_SLASH)
044                  {
045                     isTagEnd = true;
046                      continue;
047                 }
048                  if (!isTagNameEnd)
049                  {
050                     if (char.IsLetter(tagC) ||  char.IsNumber(tagC))
051                     {
052                          tag += tagC;
053                      }
054                     else
055                      {
056                         isTagNameEnd  = true;
057                     }
058                  }
059
060                 if (!string.IsNullOrEmpty(tag)) 
061                 {
062                      if (isTagNameEnd && !hasMarkTagInStack)
063                      {
064                         if (isTagEnd)
065                          {
066                              tags.Pop();
067                         } 
068                         else
069                          {
070                              tags.Push(tag);
071                         }
072                          hasMarkTagInStack = true;
073                      }
074                 }
075
076                  if (isTagNameEnd)
077                 {
078                      if (tagC == tagEndChar)
079                      {
080                         i =  tagIndex - 1;
081                         break;
082                      }
083                 } 
084
085             }
086         }
087          else
088         {
089             result += c;
090          }
091     }
092
093     while (tags.Count > 0)
094      {
095         string tag = tags.Pop();
096
097          bool isMustCloseTag = false;
098         foreach (string mustCloseTag in  mustCloseTags)
099         {
100             if  (string.Compare(mustCloseTag, tag, true) == 0)
101             {
102                  isMustCloseTag = true;
103                  break;
104             }
105         }
106          if (isMustCloseTag)
107         {
108             if  (trimHalfTag)
109             {
110                 int  lastTagIndex = result.LastIndexOf(tagStartChar.ToString() + tag,  StringComparison.CurrentCultureIgnoreCase);
111
112                  result = result.Substring(0, lastTagIndex);
113             }
114              else
115             {
116                  result += (tagStartChar.ToString() + END_SLASH + tag + tagEndChar);
117              }
118         }
119     }
120
121      return result;
122 }