您如何将HTML转换为纯文本?


99

我在表格中存储了HTML片段。不是整个页面,没有标签等,只是基本格式。

我希望能够在给定页面上将Html仅显示为文本,而无需设置格式(实际上只是前30-50个字符,但这很容易)。

如何将HTML中的“文本”作为纯文本放置在字符串中?

所以这段代码。

<b>Hello World.</b><br/><p><i>Is there anyone out there?</i><p>

成为:

你好,世界。有没有人在那里?



blackbeltcoder.com/Articles/strings/convert-html-to-text上,有一些非常简单直接的代码将HTML转换为纯文本。
乔纳森·伍德

这是我需要的正确答案-谢谢!
Shaul Behr 2012年

这里有来自W3C的一些很好的建议:w3.org/Tools/html2things.html

4
如何将一个问题标记为与六个月后提出的问题重复?似乎有点向后...
Stuart Helwig 2013年

Answers:


28

如果您在谈论标签剥离,那么不必担心<script>标签之类的事情就相对简单了。如果您只需要显示不带标签的文本,则可以使用正则表达式完成此操作:

<[^>]*>

如果您确实需要担心<script>标签之类的问题,那么您将需要比正则表达式更强大的功能,因为您需要跟踪状态,更像是上下文无关语法(CFG)。虽然您可能可以通过“从左到右”或非贪婪匹配来实现。

如果您可以使用正则表达式,那么有很多网页都有很好的信息:

如果您需要CFG的更复杂的行为,我建议您使用第三方工具,但是不幸的是,我不知道推荐哪种工具。


3
您还必须担心属性值,注释,XML中的PI / CDATA和传统HT​​ML中各种常见格式错误的>。通常,[X] [HT] ML不适合使用正则表达式进行解析。
bobince

11
这是一种可怕的方法。正确的方法是使用lib解析HTML,并遍历仅输出白名单内容的dom。
usr

2
@usr:您所指的部分是答案的CFG部分。正则表达式可用于快速,肮脏的标签剥离,虽然它有缺点,但速度快且容易。对于更复杂的解析,请使用基于CFG的工具(用您的话说就是生成DOM的lib)。我还没有执行测试,但是我认为DOM解析比正则表达式剥离要慢,以防万一需要考虑性能。
vfilby 2011年

1
@vfilby,我想到的第一个攻击是编写“ <div id = \”(c#字符串语法),请注意缺少结尾的引号和缺少的右括号,我想这会使浏览器感到困惑并失去标签结构的平衡。您想到这种攻击了吗?您能确定它永远不会起作用吗?令人讨厌
usr

1
@vfilby,解析库是否混淆都没有关系。您需要做的就是从中获取DOM(根本没有任何DOM)并仅输出列入白名单的组件。这始终是安全的,与解析的DOM的外观无关。另外,我还告诉您多个示例,其中“简单”方法将无法删除标签。
usr 2012年

96

的自由和开源HtmlAgilityPack具有在其样品中的一个方法,该方法从HTML为纯文本转换。

var plainText = HtmlUtilities.ConvertToPlainText(string html);

向其提供HTML字符串,例如

<b>hello, <i>world!</i></b>

并且您将获得纯文本结果,例如:

hello world!

10
我之前使用过HtmlAgilityPack,但看不到对ConvertToPlainText的任何引用。您能告诉我在哪里可以找到它吗?
horatio 2010年

8
霍雷肖,它包含在随HtmlAgilityPack样本之一:htmlagilitypack.codeplex.com/sourcecontrol/changeset/view/...
犹大加布里埃尔Himango

5
实际上,敏捷包中没有为此内置的方法。链接到的示例是一个使用Agility Pack遍历节点树,删除scriptstyle标记并将其他元素的内部文本写入输出字符串的示例。我怀疑它是否已通过大量实际输入的测试。
2012年

3
有人可以提供有效的代码吗,而不是链接到需要改装才能正常工作的示例的链接?
埃里克·K


51

我无法使用HtmlAgilityPack,所以我为自己写了第二好的解决方案

private static string HtmlToPlainText(string html)
{
    const string tagWhiteSpace = @"(>|$)(\W|\n|\r)+<";//matches one or more (white space or line breaks) between '>' and '<'
    const string stripFormatting = @"<[^>]*(>|$)";//match any character between '<' and '>', even when end tag is missing
    const string lineBreak = @"<(br|BR)\s{0,1}\/{0,1}>";//matches: <br>,<br/>,<br />,<BR>,<BR/>,<BR />
    var lineBreakRegex = new Regex(lineBreak, RegexOptions.Multiline);
    var stripFormattingRegex = new Regex(stripFormatting, RegexOptions.Multiline);
    var tagWhiteSpaceRegex = new Regex(tagWhiteSpace, RegexOptions.Multiline);

    var text = html;
    //Decode html specific characters
    text = System.Net.WebUtility.HtmlDecode(text); 
    //Remove tag whitespace/line breaks
    text = tagWhiteSpaceRegex.Replace(text, "><");
    //Replace <br /> with line breaks
    text = lineBreakRegex.Replace(text, Environment.NewLine);
    //Strip formatting
    text = stripFormattingRegex.Replace(text, string.Empty);

    return text;
}

2
&lt; blabla&gt; 被解析,所以我移动了文本= System.Net.WebUtility.HtmlDecode(text); 到方法的底部
Luuk

1
太好了,我还添加了一个多空间冷凝器,因为html可能是从CMS生成的:var spaceRegex = new Regex(“ [] {2,}”,RegexOptions.None);
Enkode '16

有时,在html代码中有编码器的新行(注释中看不到新行,因此我以[新行]进行显示,例如:<br>我[新行]错过了[新行]您<br >,因此它假定显示:“我想念您”,但它显示我[新行]想念[新行]您。这使纯文本看起来很痛苦。您知道如何解决吗?
123iamking

@ 123iamking您可以在返回文本之前使用它;:text.Replace(“ [换行]”,“ \ n”);
Eslam Badawy

我正在使用它,并且意识到有时它会在字符串的开头留下'>'。应用正则表达式<[^>] *>的其他解决方案效果很好。
Etienne Charland

20

HTTPUtility.HTMLEncode()用于将HTML标签编码为字符串。它为您处理所有繁重的工作。从MSDN文档

如果在HTTP流中传递诸如空格和标点符号之类的字符,则在接收端可能会误解它们。HTML编码将HTML中不允许的字符转换为等效的字符实体;HTML解码会逆转编码。例如,当嵌入在文本块中时,字符<和将>被编码为&lt;&gt;用于HTTP传输。

HTTPUtility.HTMLEncode()方法,在这里详细介绍:

public static void HtmlEncode(
  string s,
  TextWriter output
)

用法:

String TestString = "This is a <Test String>.";
StringWriter writer = new StringWriter();
Server.HtmlEncode(TestString, writer);
String EncodedString = writer.ToString();

George的回答非常好,它也突出了我第一次问这个问题的能力。抱歉。
Stuart Helwig

html敏捷包已过期且不支持html5
abzarak 2015年

10

要添加到vfilby的答案中,您只需在代码中执行RegEx替换即可;不需要新的课程。万一像我这样的其他新手在这个问题上脚。

using System.Text.RegularExpressions;

然后...

private string StripHtml(string source)
{
        string output;

        //get rid of HTML tags
        output = Regex.Replace(source, "<[^>]*>", string.Empty);

        //get rid of multiple blank lines
        output = Regex.Replace(output, @"^\s*$\n", string.Empty, RegexOptions.Multiline);

        return output;
}

19
不好!可以通过省略右尖括号来欺骗包含脚本。伙计们,千万不要做黑名单。您无法通过将其列入黑名单清除输入。错了
usr

7

将HTML转换为纯文本的三步过程

首先,您需要为HtmlAgilityPack安装Nuget软件包。 其次,请创建此类

public class HtmlToText
{
    public HtmlToText()
    {
    }

    public string Convert(string path)
    {
        HtmlDocument doc = new HtmlDocument();
        doc.Load(path);

        StringWriter sw = new StringWriter();
        ConvertTo(doc.DocumentNode, sw);
        sw.Flush();
        return sw.ToString();
    }

    public string ConvertHtml(string html)
    {
        HtmlDocument doc = new HtmlDocument();
        doc.LoadHtml(html);

        StringWriter sw = new StringWriter();
        ConvertTo(doc.DocumentNode, sw);
        sw.Flush();
        return sw.ToString();
    }

    private void ConvertContentTo(HtmlNode node, TextWriter outText)
    {
        foreach(HtmlNode subnode in node.ChildNodes)
        {
            ConvertTo(subnode, outText);
        }
    }

    public void ConvertTo(HtmlNode node, TextWriter outText)
    {
        string html;
        switch(node.NodeType)
        {
            case HtmlNodeType.Comment:
                // don't output comments
                break;

            case HtmlNodeType.Document:
                ConvertContentTo(node, outText);
                break;

            case HtmlNodeType.Text:
                // script and style must not be output
                string parentName = node.ParentNode.Name;
                if ((parentName == "script") || (parentName == "style"))
                    break;

                // get text
                html = ((HtmlTextNode)node).Text;

                // is it in fact a special closing node output as text?
                if (HtmlNode.IsOverlappedClosingElement(html))
                    break;

                // check the text is meaningful and not a bunch of whitespaces
                if (html.Trim().Length > 0)
                {
                    outText.Write(HtmlEntity.DeEntitize(html));
                }
                break;

            case HtmlNodeType.Element:
                switch(node.Name)
                {
                    case "p":
                        // treat paragraphs as crlf
                        outText.Write("\r\n");
                        break;
                }

                if (node.HasChildNodes)
                {
                    ConvertContentTo(node, outText);
                }
                break;
        }
    }
}

通过参考犹大Himango的答案使用上述类

第三,您需要创建上述类的Object和Use ConvertHtml(HTMLContent)Method来将HTML转换为纯文本,而不是ConvertToPlainText(string html);

HtmlToText htt=new HtmlToText();
var plainText = htt.ConvertHtml(HTMLContent);

我可以跳过转换html中的链接吗?转换为文本时,我需要在html中保留链接吗?
coder771

6

它的局限性在于它不会折叠长的行内空格,但绝对是可移植的,并且尊重Web浏览器之类的布局。

static string HtmlToPlainText(string html) {
  string buf;
  string block = "address|article|aside|blockquote|canvas|dd|div|dl|dt|" +
    "fieldset|figcaption|figure|footer|form|h\\d|header|hr|li|main|nav|" +
    "noscript|ol|output|p|pre|section|table|tfoot|ul|video";

  string patNestedBlock = $"(\\s*?</?({block})[^>]*?>)+\\s*";
  buf = Regex.Replace(html, patNestedBlock, "\n", RegexOptions.IgnoreCase);

  // Replace br tag to newline.
  buf = Regex.Replace(buf, @"<(br)[^>]*>", "\n", RegexOptions.IgnoreCase);

  // (Optional) remove styles and scripts.
  buf = Regex.Replace(buf, @"<(script|style)[^>]*?>.*?</\1>", "", RegexOptions.Singleline);

  // Remove all tags.
  buf = Regex.Replace(buf, @"<[^>]*(>|$)", "", RegexOptions.Multiline);

  // Replace HTML entities.
  buf = WebUtility.HtmlDecode(buf);
  return buf;
}

4

HtmlAgilityPack中没有名为“ ConvertToPlainText”的方法,但是您可以使用以下方法将html字符串转换为CLEAR字符串:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(htmlString);
var textString = doc.DocumentNode.InnerText;
Regex.Replace(textString , @"<(.|n)*?>", string.Empty).Replace("&nbsp", "");

那对我有用。但是我没有在“ HtmlAgilityPack”中找到名称为“ ConvertToPlainText”的方法。


3

我认为最简单的方法是制作“字符串”扩展方法(基于用户Richard的建议):

using System;
using System.Text.RegularExpressions;

public static class StringHelpers
{
    public static string StripHTML(this string HTMLText)
        {
            var reg = new Regex("<[^>]+>", RegexOptions.IgnoreCase);
            return reg.Replace(HTMLText, "");
        }
}

然后,只需对程序中的任何“字符串”变量使用此扩展方法:

var yourHtmlString = "<div class=\"someclass\"><h2>yourHtmlText</h2></span>";
var yourTextString = yourHtmlString.StripHTML();

我使用此扩展方法将html格式的注释转换为纯文本,以便将其正确显示在水晶报表上,并且效果很好!


3

我找到的最简单的方法是:

HtmlFilter.ConvertToPlainText(html);

HtmlFilter类位于Microsoft.TeamFoundation.WorkItemTracking.Controls.dll中

可以在以下文件夹中找到该dll:%ProgramFiles%\ Common Files \ microsoft shared \ Team Foundation Server \ 14.0 \

在VS 2015中,该dll还需要引用位于同一文件夹中的Microsoft.TeamFoundation.WorkItemTracking.Common.dll。


它可以处理脚本标签吗?它的格式是否为粗斜体等?
萨姆拉(Samra)

引入了一个团队基础依赖性,用于将html转换为纯文本,这是非常可疑的……
ViRuSTriNiTy

2

如果您有带有HTML标记的数据,并且想要显示它以便一个人可以看到这些标记,请使用HttpServerUtility :: HtmlEncode。

如果您的数据中包含HTML标记,并且希望用户看到呈现的标记,请按原样显示文本。如果文字代表整个网页,请使用IFRAME。

如果您有带有HTML标记的数据,并且想要剥离标记并仅显示未格式化的文本,请使用正则表达式。


在PHP中有一个函数调用striptags(),也许你有类似的东西
马库斯

“使用正则表达式”不行!这将被列入黑名单。您只能安全地列入白名单。例如,您还记得谁的样式标题可以包含“ background:url('javascript:...');”?当然不会,我也不会。这就是为什么黑名单不起作用的原因。
usr

2

我曾经遇到过类似的问题,并找到了最佳解决方案。下面的代码对我来说很完美。

  private string ConvertHtml_Totext(string source)
    {
     try
      {
      string result;

    // Remove HTML Development formatting
    // Replace line breaks with space
    // because browsers inserts space
    result = source.Replace("\r", " ");
    // Replace line breaks with space
    // because browsers inserts space
    result = result.Replace("\n", " ");
    // Remove step-formatting
    result = result.Replace("\t", string.Empty);
    // Remove repeating spaces because browsers ignore them
    result = System.Text.RegularExpressions.Regex.Replace(result,
                                                          @"( )+", " ");

    // Remove the header (prepare first by clearing attributes)
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"<( )*head([^>])*>","<head>",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"(<( )*(/)( )*head( )*>)","</head>",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             "(<head>).*(</head>)",string.Empty,
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);

    // remove all scripts (prepare first by clearing attributes)
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"<( )*script([^>])*>","<script>",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"(<( )*(/)( )*script( )*>)","</script>",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    //result = System.Text.RegularExpressions.Regex.Replace(result,
    //         @"(<script>)([^(<script>\.</script>)])*(</script>)",
    //         string.Empty,
    //         System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"(<script>).*(</script>)",string.Empty,
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);

    // remove all styles (prepare first by clearing attributes)
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"<( )*style([^>])*>","<style>",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"(<( )*(/)( )*style( )*>)","</style>",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             "(<style>).*(</style>)",string.Empty,
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);

    // insert tabs in spaces of <td> tags
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"<( )*td([^>])*>","\t",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);

    // insert line breaks in places of <BR> and <LI> tags
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"<( )*br( )*>","\r",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"<( )*li( )*>","\r",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);

    // insert line paragraphs (double line breaks) in place
    // if <P>, <DIV> and <TR> tags
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"<( )*div([^>])*>","\r\r",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"<( )*tr([^>])*>","\r\r",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"<( )*p([^>])*>","\r\r",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);

    // Remove remaining tags like <a>, links, images,
    // comments etc - anything that's enclosed inside < >
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"<[^>]*>",string.Empty,
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);

    // replace special characters:
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @" "," ",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);

    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"&bull;"," * ",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"&lsaquo;","<",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"&rsaquo;",">",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"&trade;","(tm)",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"&frasl;","/",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"&lt;","<",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"&gt;",">",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"&copy;","(c)",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"&reg;","(r)",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    // Remove all others. More can be added, see
    // http://hotwired.lycos.com/webmonkey/reference/special_characters/
    result = System.Text.RegularExpressions.Regex.Replace(result,
             @"&(.{2,6});", string.Empty,
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);

    // for testing
    //System.Text.RegularExpressions.Regex.Replace(result,
    //       this.txtRegex.Text,string.Empty,
    //       System.Text.RegularExpressions.RegexOptions.IgnoreCase);

    // make line breaking consistent
    result = result.Replace("\n", "\r");

    // Remove extra line breaks and tabs:
    // replace over 2 breaks with 2 and over 4 tabs with 4.
    // Prepare first to remove any whitespaces in between
    // the escaped characters and remove redundant tabs in between line breaks
    result = System.Text.RegularExpressions.Regex.Replace(result,
             "(\r)( )+(\r)","\r\r",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             "(\t)( )+(\t)","\t\t",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             "(\t)( )+(\r)","\t\r",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    result = System.Text.RegularExpressions.Regex.Replace(result,
             "(\r)( )+(\t)","\r\t",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    // Remove redundant tabs
    result = System.Text.RegularExpressions.Regex.Replace(result,
             "(\r)(\t)+(\r)","\r\r",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    // Remove multiple tabs following a line break with just one tab
    result = System.Text.RegularExpressions.Regex.Replace(result,
             "(\r)(\t)+","\r\t",
             System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    // Initial replacement target string for line breaks
    string breaks = "\r\r\r";
    // Initial replacement target string for tabs
    string tabs = "\t\t\t\t\t";
    for (int index=0; index<result.Length; index++)
    {
        result = result.Replace(breaks, "\r\r");
        result = result.Replace(tabs, "\t\t\t\t");
        breaks = breaks + "\r";
        tabs = tabs + "\t";
    }

    // That's it.
    return result;
}
catch
{
    MessageBox.Show("Error");
    return source;
}

}

必须先删除\ n和\ r之类的转义字符,因为它们会导致正则表达式按预期停止工作。

此外,为了使结果字符串正确显示在文本框中,可能需要将其拆分并设置文本框的Lines属性,而不是分配给Text属性。

this.txtResult.Lines = StripHTML(this.txtSource.Text).Split(“ \ r” .ToCharArray());

来源:https : //www.codeproject.com/Articles/11902/Convert-HTML-to-Plain-Text-2


0

取决于您所说的“ html”。最复杂的情​​况是完整的网页。这也是最简单的处理方式,因为您可以使用文本模式的Web浏览器。请参阅Wikipedia文章,其中列出了Web浏览器,包括文本模式浏览器。Lynx可能是最著名的,但其中之一可能会更好地满足您的需求。


正如他所说:“我在表格中存储了一些HTML片段。”
M在

0

这是我的解决方案:

public string StripHTML(string html)
{
    var regex = new Regex("<[^>]+>", RegexOptions.IgnoreCase);
    return System.Web.HttpUtility.HtmlDecode((regex.Replace(html, "")));
}

例:

StripHTML("<p class='test' style='color:red;'>Here is my solution:</p>");
// output -> Here is my solution:

0

我有同样的问题,只是我的html有一个简单的已知布局,例如:

<DIV><P>abc</P><P>def</P></DIV>

所以我最终使用了这样简单的代码:

string.Join (Environment.NewLine, XDocument.Parse (html).Root.Elements ().Select (el => el.Value))

哪个输出:

abc
def

0

没有写,而是使用:

using HtmlAgilityPack;
using System;
using System.IO;
using System.Text.RegularExpressions;

namespace foo {
  //small but important modification to class https://github.com/zzzprojects/html-agility-pack/blob/master/src/Samples/Html2Txt/HtmlConvert.cs
  public static class HtmlToText {

    public static string Convert(string path) {
      HtmlDocument doc = new HtmlDocument();
      doc.Load(path);
      return ConvertDoc(doc);
    }

    public static string ConvertHtml(string html) {
      HtmlDocument doc = new HtmlDocument();
      doc.LoadHtml(html);
      return ConvertDoc(doc);
    }

    public static string ConvertDoc(HtmlDocument doc) {
      using (StringWriter sw = new StringWriter()) {
        ConvertTo(doc.DocumentNode, sw);
        sw.Flush();
        return sw.ToString();
      }
    }

    internal static void ConvertContentTo(HtmlNode node, TextWriter outText, PreceedingDomTextInfo textInfo) {
      foreach (HtmlNode subnode in node.ChildNodes) {
        ConvertTo(subnode, outText, textInfo);
      }
    }
    public static void ConvertTo(HtmlNode node, TextWriter outText) {
      ConvertTo(node, outText, new PreceedingDomTextInfo(false));
    }
    internal static void ConvertTo(HtmlNode node, TextWriter outText, PreceedingDomTextInfo textInfo) {
      string html;
      switch (node.NodeType) {
        case HtmlNodeType.Comment:
          // don't output comments
          break;
        case HtmlNodeType.Document:
          ConvertContentTo(node, outText, textInfo);
          break;
        case HtmlNodeType.Text:
          // script and style must not be output
          string parentName = node.ParentNode.Name;
          if ((parentName == "script") || (parentName == "style")) {
            break;
          }
          // get text
          html = ((HtmlTextNode)node).Text;
          // is it in fact a special closing node output as text?
          if (HtmlNode.IsOverlappedClosingElement(html)) {
            break;
          }
          // check the text is meaningful and not a bunch of whitespaces
          if (html.Length == 0) {
            break;
          }
          if (!textInfo.WritePrecedingWhiteSpace || textInfo.LastCharWasSpace) {
            html = html.TrimStart();
            if (html.Length == 0) { break; }
            textInfo.IsFirstTextOfDocWritten.Value = textInfo.WritePrecedingWhiteSpace = true;
          }
          outText.Write(HtmlEntity.DeEntitize(Regex.Replace(html.TrimEnd(), @"\s{2,}", " ")));
          if (textInfo.LastCharWasSpace = char.IsWhiteSpace(html[html.Length - 1])) {
            outText.Write(' ');
          }
          break;
        case HtmlNodeType.Element:
          string endElementString = null;
          bool isInline;
          bool skip = false;
          int listIndex = 0;
          switch (node.Name) {
            case "nav":
              skip = true;
              isInline = false;
              break;
            case "body":
            case "section":
            case "article":
            case "aside":
            case "h1":
            case "h2":
            case "header":
            case "footer":
            case "address":
            case "main":
            case "div":
            case "p": // stylistic - adjust as you tend to use
              if (textInfo.IsFirstTextOfDocWritten) {
                outText.Write("\r\n");
              }
              endElementString = "\r\n";
              isInline = false;
              break;
            case "br":
              outText.Write("\r\n");
              skip = true;
              textInfo.WritePrecedingWhiteSpace = false;
              isInline = true;
              break;
            case "a":
              if (node.Attributes.Contains("href")) {
                string href = node.Attributes["href"].Value.Trim();
                if (node.InnerText.IndexOf(href, StringComparison.InvariantCultureIgnoreCase) == -1) {
                  endElementString = "<" + href + ">";
                }
              }
              isInline = true;
              break;
            case "li":
              if (textInfo.ListIndex > 0) {
                outText.Write("\r\n{0}.\t", textInfo.ListIndex++);
              } else {
                outText.Write("\r\n*\t"); //using '*' as bullet char, with tab after, but whatever you want eg "\t->", if utf-8 0x2022
              }
              isInline = false;
              break;
            case "ol":
              listIndex = 1;
              goto case "ul";
            case "ul": //not handling nested lists any differently at this stage - that is getting close to rendering problems
              endElementString = "\r\n";
              isInline = false;
              break;
            case "img": //inline-block in reality
              if (node.Attributes.Contains("alt")) {
                outText.Write('[' + node.Attributes["alt"].Value);
                endElementString = "]";
              }
              if (node.Attributes.Contains("src")) {
                outText.Write('<' + node.Attributes["src"].Value + '>');
              }
              isInline = true;
              break;
            default:
              isInline = true;
              break;
          }
          if (!skip && node.HasChildNodes) {
            ConvertContentTo(node, outText, isInline ? textInfo : new PreceedingDomTextInfo(textInfo.IsFirstTextOfDocWritten) { ListIndex = listIndex });
          }
          if (endElementString != null) {
            outText.Write(endElementString);
          }
          break;
      }
    }
  }
  internal class PreceedingDomTextInfo {
    public PreceedingDomTextInfo(BoolWrapper isFirstTextOfDocWritten) {
      IsFirstTextOfDocWritten = isFirstTextOfDocWritten;
    }
    public bool WritePrecedingWhiteSpace { get; set; }
    public bool LastCharWasSpace { get; set; }
    public readonly BoolWrapper IsFirstTextOfDocWritten;
    public int ListIndex { get; set; }
  }
  internal class BoolWrapper {
    public BoolWrapper() { }
    public bool Value { get; set; }
    public static implicit operator bool(BoolWrapper boolWrapper) {
      return boolWrapper.Value;
    }
    public static implicit operator BoolWrapper(bool boolWrapper) {
      return new BoolWrapper { Value = boolWrapper };
    }
  }
}

0

我认为它有一个简单的答案:

public string RemoveHTMLTags(string HTMLCode)
{
    string str=System.Text.RegularExpressions.Regex.Replace(HTMLCode, "<[^>]*>", "");
    return str;
}

0

对于寻求针对给定html文档的文本缩写,没有换行符和HTML标记的OP问题的确切解决方案的任何人,请在下面找到解决方案。

与每个建议的解决方案一样,以下代码也有一些假设:

  • 脚本或样式标签不应包含脚本和样式标签作为脚本的一部分
  • 只有主要的内联元素将被内联而没有空格,即he<span>ll</span>o应该输出hello。内联标签列表:https : //www.w3schools.com/htmL/html_blocks.asp

考虑到上述情况,以下带有已编译正则表达式的字符串扩展名将输出有关html转义字符的预期纯文本,而在null输入中将输出null。

public static class StringExtensions
{
    public static string ConvertToPlain(this string html)
    {
        if (html == null)
        {
            return html;
        }

        html = scriptRegex.Replace(html, string.Empty);
        html = inlineTagRegex.Replace(html, string.Empty);
        html = tagRegex.Replace(html, " ");
        html = HttpUtility.HtmlDecode(html);
        html = multiWhitespaceRegex.Replace(html, " ");

        return html.Trim();
    }

    private static readonly Regex inlineTagRegex = new Regex("<\\/?(a|span|sub|sup|b|i|strong|small|big|em|label|q)[^>]*>", RegexOptions.Compiled | RegexOptions.Singleline);
    private static readonly Regex scriptRegex = new Regex("<(script|style)[^>]*?>.*?</\\1>", RegexOptions.Compiled | RegexOptions.Singleline);
    private static readonly Regex tagRegex = new Regex("<[^>]+>", RegexOptions.Compiled | RegexOptions.Singleline);
    private static readonly Regex multiWhitespaceRegex = new Regex("\\s+", RegexOptions.Compiled | RegexOptions.Singleline);
}

-4

公共静态字符串StripTags2(string html){return html.Replace(“ <”,“ <”)。Replace(“>”,“>”); }

这样,您可以将字符串中的所有“ <”和“>”转义。这是你想要的吗?


...啊。现在,答案(连同对模棱两可的问题的解释)已经完全改变,我将在缺少&的情况下选择nits。编码代替。;-)
bobince

2
我认为重新发明轮子不是一个好主意-尤其是当轮子是正方形的时候。您应该改用HTMLEncode。
Kramii
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.