C# 获取HTML内容的前100个字符,而不剥离标记
关于如何剥离html标记有很多问题,但关于关闭它们的函数/方法的问题并不多。 情况是这样的。我有一个500个字符的消息摘要(包括html标记),但我只想要前100个字符。问题是如果我截断消息,它可能在HTML标签的中间…把事情搞砸了 假设html是这样的:C# 获取HTML内容的前100个字符,而不剥离标记,c#,asp.net,html,C#,Asp.net,Html,关于如何剥离html标记有很多问题,但关于关闭它们的函数/方法的问题并不多。 情况是这样的。我有一个500个字符的消息摘要(包括html标记),但我只想要前100个字符。问题是如果我截断消息,它可能在HTML标签的中间…把事情搞砸了 假设html是这样的: “知识产权是一种权利,是一种精英,是劳动和财富的临时契约。 一些日期:2010年4月30日至5月2日 但是,在最低限度的情况下,我们必须遵守《劳动法》的规定,不因共同利益而放弃劳动。两人或两人的共同利益是不可分割的,因为他们的权利是不可分割的
“知识产权是一种权利,是一种精英,是劳动和财富的临时契约。
一些日期:2010年4月30日至5月2日
但是,在最低限度的情况下,我们必须遵守《劳动法》的规定,不因共同利益而放弃劳动。两人或两人的共同利益是不可分割的,因为他们的权利是不可分割的。除了偶尔出于谨慎的考虑,不能因职权而受到惩罚。
有关Lorem Ipsum Doemdloye的更多信息,请访问:
我应该如何获取前100个左右的字符?(不过,理想情况下,应该是“内容”(在html标记之间)的前大约100个字符)
我假设实现这一点的最佳方法是一个递归算法,它跟踪html标记并附加任何被截断的标记,但这可能不是最好的方法
我的第一个想法是使用递归计算嵌套标记,当我们达到100个字符时,寻找下一个“如果将HTML解析为DOM结构,然后开始遍历广度优先或深度优先,收集节点文本,直到达到100个字符,会怎么样?过去我用正则表达式完成了这项工作。抓取内容,通过正则表达式去掉标记,然后将其修剪到所需的长度
当然,它删除了所有的HTML,这就是我想要的。如果你想保留HTML,我会考虑不关闭打开的标签,而是删除打开的标签。
我的建议是找到一个HTML友好的遍历器(一个让你遍历HTML样的XML)。然后从最开始的标签开始忽略标签本身,只计算标签中的数据。将其计算到你的极限,然后一旦达到极限,就关闭每个标签(我想不出任何标签不仅仅是标签) 这应该是相当好的工作,并相当接近你所寻找的这完全是老生常谈,所以我假设会有一些棘手的部分,比如显示的属性值(比如链接标签值)。我决定推出自己的解决方案……只是为了迎接挑战 如果有人看到任何逻辑错误或效率低下,请告诉我 我不知道这是否是最好的方法…但它似乎有效。可能有些情况下它不起作用…如果html不正确,它可能会失败
/// <summary>
/// Get the first n characters of some html text
/// </summary>
private string truncateTo(string s, int howMany, string ellipsis) {
// return entire string if it's more than n characters
if (s.Length < howMany)
return s;
Stack<string> elements = new Stack<string>();
StringBuilder sb = new StringBuilder();
int trueCount = 0;
for (int i = 0; i < s.Length; i++) {
if (s[i] == '<') {
StringBuilder elem = new StringBuilder();
bool selfclosing = false;
if (s[i + 1] == '/') {
elements.Pop(); // Take the previous element off the stack
while (s[i] != '>') {
i++;
}
}
else { // not a closing tag so get the element name
while (i < s.Length && s[i] != '>') {
if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) {
elem.Append(s[i]);
}
else if (s[i] == '/' || s[i] == ' ') {
// self closing tag or end of tag name. Find the end of tag
do {
if (s[i] == '/' && s[i + 1] == '>') {
// at the end of self-closing tag. Don't store
selfclosing = true;
}
i++;
} while (i < s.Length && s[i] != '>');
}
i++;
} // end while( != '>' )
if (!selfclosing)
elements.Push(elem.ToString());
}
}
else {
trueCount++;
if (trueCount > howMany) {
sb.Append(s.Substring(0, i - 1));
sb.Append(ellipsis);
while (elements.Count > 0) {
sb.AppendFormat("</{0}>", elements.Pop());
}
}
}
}
return sb.ToString();
}
//
///获取某些html文本的前n个字符
///
私有字符串truncateTo(字符串s,整数多少,字符串省略号){
//如果超过n个字符,则返回整个字符串
如果(s.长度<多少)
返回s;
堆栈元素=新堆栈();
StringBuilder sb=新的StringBuilder();
int-trueCount=0;
对于(int i=0;i'){
如果((s[i]>='a'和&s[i]='a'和&s[i]');
}
i++;
}//结束时(!=“>”)
如果(!自动关闭)
elements.Push(elem.ToString());
}
}
否则{
trueCount++;
如果(trueCount>多少){
sb.Append(s.Substring(0,i-1));
某人附加(省略号);
而(elements.Count>0){
sb.AppendFormat(“,elements.Pop());
}
}
}
}
使某人返回字符串();
}
我使用了XmlReader和XmlWriter来实现这一点:
正如其他人在这里提到的,您可能应该使用SgmlReader或HtmlAgilityPack来调整传入字符串的大小。这是大多数情况下的解决方案。它不会处理不正确的html标记和类似“ac”的情况。但它适用于我的目的,可能会对其他人有所帮助
/// <summary>
/// Gets first number of characters from the html string without stripping tags
/// </summary>
/// <param name="htmlString">The html string, not encoded, pure html</param>
/// <param name="length">The number of first characters to get</param>
/// <returns>The html string</returns>
public static string GetFirstCharacters(string htmlString, int length)
{
if (htmlString == null)
return string.Empty;
if(htmlString.Length < length)
return htmlString;
// regex to separate string on parts: tags, texts
var separateRegex = new Regex("([^>][^<>]*[^<])|[\\S]{1}");
// regex to identify tags
var tagsRegex = new Regex("^<[^>]+>$");
// separate string on tags and texts
var matches = separateRegex.Matches(htmlString);
// looping by mathes
// if it's a tag then just append it to resuls,
// if it's a text then append substing of it (considering the number of characters)
var counter = 0;
var sb = new StringBuilder();
for (var i = 0; i < matches.Count; i++)
{
var m = matches[i].Value;
// check if it's a tag
if (tagsRegex.IsMatch(m))
{
sb.Append(m);
}
else
{
var lengthToCut = length - counter;
var sub = lengthToCut >= m.Length
? m
: m.Substring(0, lengthToCut);
counter += sub.Length;
sb.Append(sub);
}
}
return sb.ToString();
}
//
///从html字符串中获取第一个字符数,而不剥离标记
///
///html字符串,未编码,纯html
///要获取的第一个字符数
///html字符串
公共静态字符串GetFirstCharacters(字符串htmlString,整数长度)
{
if(htmlString==null)
返回字符串。空;
if(htmlString.Length][^]*[^$”;
//标记和文本上的分隔字符串
var matches=separateRegex.matches(htmlString);
//mathes循环
//如果它是一个标记,那么只需将其附加到results中,
//如果是文本,则附加其子字符串(考虑字符数)
var计数器=0;
var sb=新的StringBuilder();
for(var i=0;i=米长度
M
:m.子字符串(0,长度tocut);
计数器+=子长度;
某人追加(分);
}
}
使某人返回字符串();
}
<
} while (i < s.Length && s[i] != '>');
} while (i < s.Length && ***s[i+1]*** != '>');