Как преобразовать HTML в обычный текст?

99

У меня есть фрагменты Html, хранящиеся в таблице. Не целые страницы, без тегов и т.п., а только базовое форматирование.

Я хотел бы иметь возможность отображать этот Html только как текст, без форматирования , на данной странице (на самом деле только первые 30-50 символов, но это простой бит).

Как мне поместить «текст» в этом HTML в строку как обычный текст?

Итак, этот фрагмент кода.

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

Становится:

Привет мир. Есть там кто-нибудь?

Стюарт Хельвиг
источник
Вы можете использовать SgmlReader. code.msdn.microsoft.com/SgmlReader
Леонардо Эррера
На сайте blackbeltcoder.com/Articles/strings/convert-html-to-text есть довольно простой и понятный код для преобразования HTML в обычный текст .
Джонатан Вуд,
Это был правильный ответ на то, что мне было нужно - спасибо!
Shaul Behr
Вот несколько хороших предложений от W3C: w3.org/Tools/html2things.html
Rich
4
Как вопрос может быть отмечен как дубликат вопроса, заданного 6 месяцев спустя? Кажется немного отсталым ...
Стюарт Хельвиг

Ответы:

28

Если вы говорите об удалении тегов, это относительно просто, если вам не нужно беспокоиться о таких вещах, как <script>теги. Если все, что вам нужно сделать, это отобразить текст без тегов, вы можете сделать это с помощью регулярного выражения:

<[^>]*>

Если вам действительно нужно беспокоиться о <script>тегах и тому подобном, вам понадобится что-то немного более мощное, чем регулярные выражения, потому что вам нужно отслеживать состояние, что-то вроде контекстно-свободной грамматики (CFG). Хотя вы могли бы сделать это с помощью «слева направо» или не жадного сопоставления.

Если вы умеете использовать регулярные выражения, существует множество веб-страниц с хорошей информацией:

Если вам нужно более сложное поведение CFG, я бы посоветовал использовать сторонний инструмент, к сожалению, я не знаю хорошего, что можно порекомендовать.

vfilby
источник
3
Вам также нужно беспокоиться о> в значениях атрибутов, комментариях, PI / CDATA в XML и различных распространенных искажениях в устаревшем HTML. В общем случае [X] [HT] ML не поддается синтаксическому анализу с помощью регулярных выражений.
bobince
11
Это ужасный способ сделать это. Правильный способ - проанализировать HTML с помощью библиотеки и пройти по dom, выводя только содержимое из белого списка.
usr
2
@usr: Вы имеете в виду часть ответа CFG. Regex можно использовать для быстрого и грязного удаления тегов, у него есть свои слабые места, но это быстро и легко. Для более сложного анализа используйте инструмент на основе CFG (на вашем языке библиотека, которая генерирует DOM). Я не проводил тесты, но держу пари, что синтаксический анализ DOM медленнее, чем удаление регулярных выражений, в случае, если необходимо учитывать производительность.
vfilby
1
@vfilby, первая атака, которая приходит на ум, - это написание "<div id = \" "(строковый синтаксис C #). Обратите внимание на отсутствующие конечные кавычки и закрывающую скобку. Я думаю, это запутает браузер и разбалансирует структуру тегов. вы думаете об этой атаке? Можете ли вы быть уверены, что она никогда не сработает? Противно.
usr
1
@vfilby, неважно, запуталась ли библиотека синтаксического анализа. Все, что вам нужно сделать, это взять из него DOM (любой DOM) и вывести только компоненты из белого списка. Это всегда безопасно, не имеет значения, как выглядит проанализированная DOM. Кроме того, я привел несколько примеров, когда ваш «простой» метод не удаляет теги.
usr
97

В одном из примеров бесплатного HtmlAgilityPack с открытым исходным кодом есть метод, который преобразует HTML в обычный текст.

var plainText = HtmlUtilities.ConvertToPlainText(string html);

Подайте ему строку HTML, например

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

И вы получите результат в виде простого текста, например:

hello world!
Иуда Габриэль Химанго
источник
10
Раньше я использовал HtmlAgilityPack, но не вижу ссылки на ConvertToPlainText. Вы можете сказать мне, где я могу его найти?
horatio 08
8
Горацио, он включен в один из примеров, поставляемых с HtmlAgilityPack: htmlagilitypack.codeplex.com/sourcecontrol/changeset/view/…
Джуда Габриэль Химанго
5
На самом деле, в Agility Pack для этого нет встроенного метода. Вы связались с примером, в котором Agility Pack используется для обхода дерева узлов, удаления scriptи styleтегов и записи внутреннего текста других элементов в выходную строку. Я сомневаюсь, что он прошел много испытаний с реальными данными.
Lou
3
Может ли кто-нибудь предоставить код, который работает, а не ссылки на образцы, которые необходимо модернизировать для правильной работы?
Eric K
6
Образец теперь можно найти здесь: github.com/ceee/ReadSharp/blob/master/ReadSharp/…
StuartQ
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; был проанализирован, поэтому я переместил text = System.Net.WebUtility.HtmlDecode (text); в
конец
1
Это было здорово, я также добавил конденсатор с несколькими пространствами, так как html мог быть сгенерирован из CMS: var spaceRegex = new Regex ("[] {2,}", RegexOptions.None);
Enkode
Иногда в html-коде есть новая строка кодера (новую строку нельзя увидеть в комментарии, поэтому я показываю ее с помощью [новой строки], например: <br> Я [новая строка] пропускаю [новую строку] you <br >. Предполагается, что отображается: «Я скучаю по тебе», но это показывает, что я [новая строка] скучаю по [новой строке] по тебе. Это заставляет простой текст выглядеть болезненно. Вы знаете, как исправить?
123iamking
@ 123iamking можно использовать перед текстом возврата; : text.Replace ("[новая строка]", "\ n");
Эслам Бадави
Я использовал это и понял, что иногда он оставляет '>' в начале строк. Другое решение применения регулярного выражения <[^>] *> отлично работает.
Этьен
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();
Джордж Стокер
источник
Действительно хороший ответ, Джордж, спасибо, он также подчеркнул, насколько плохо я задал вопрос в первый раз. Сожалею.
Стюарт Хельвиг
html agility pack
устарел
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;
}
WEFX
источник
19
НЕ ХОРОШО! Его можно обмануть, чтобы он содержал сценарий, опустив закрывающую угловую скобку. РЕБЯТА, никогда не заносите в черный список. Вы не можете дезинфицировать ввод путем внесения в черный список. Это так неправильно.
usr
7

Трехэтапный процесс преобразования HTML в простой текст

Сначала вам нужно установить пакет Nuget для HtmlAgilityPack. Во-вторых, создайте этот класс.

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;
        }
    }
}

Используя приведенный выше класс со ссылкой на ответ Иуды Химанго

В-третьих, вам нужно создать объект класса выше и использовать ConvertHtml(HTMLContent)метод для преобразования HTML в обычный текст, а неConvertToPlainText(string html);

HtmlToText htt=new HtmlToText();
var plainText = htt.ConvertHtml(HTMLContent);
Abdulqadir_WDDN
источник
Могу ли я пропустить преобразование ссылок в HTML. мне нужно сохранить ссылки в HTML при преобразовании в текст?
coder771 06
6

У него есть ограничение, заключающееся в том, что он не сворачивает длинные строчные пробелы, но он определенно переносим и уважает макет, как веб-браузер.

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;
}
Jeiea
источник
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", "");

Это работает для меня. НО Я НЕ НАШЕЛ МЕТОД С ИМЯ «ConvertToPlainText» В «HtmlAgilityPack».

Амин
источник
3

Я думаю, что самый простой способ - создать метод расширения строки (на основе того, что предложил пользователь Ричард):

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, расположенный в той же папке.

Роман О
источник
заботится ли он о тегах скрипта, выделяется ли он жирным курсивом и т. д.?
Самра
Представляем зависимость от командной основы для преобразования 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;
}

}

Сначала нужно было удалить escape-символы, такие как \ 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». Самый сложный случай - это целые веб-страницы. С этим также легче всего справиться, поскольку вы можете использовать веб-браузер в текстовом режиме. См. Статью Википедии со списком веб-браузеров, включая браузеры с текстовым режимом. Lynx, вероятно, самый известный, но один из других может быть лучше для ваших нужд.

mpez0
источник
как он сказал: «У меня есть фрагменты HTML-кода, хранящиеся в таблице».
М.,
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;
}
user3077654
источник
0

Для тех, кто ищет точное решение вопроса OP для текстового сокращения данного html-документа без символов новой строки и HTML-тегов, пожалуйста, найдите решение ниже.

Как и в случае любого предлагаемого решения, в приведенном ниже коде есть некоторые предположения:

  • теги сценария или стиля не должны содержать теги сценария и стиля как часть сценария
  • только основные встроенные элементы будут встроены без пробелов, т.е. 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 (строка html) {return html.Replace ("<", "<"). Replace (">", ">"); }

Этим вы избегаете всех «<» и «>» в ​​строке. Это то, что вы хотите?

Хосе Леаль
источник
... ах. Что ж, теперь ответ (вместе с толкованием двусмысленного вопроса) полностью изменился, я выберу гниды из-за отсутствия & amp; кодирование вместо этого. ;-)
bobince
2
Я не думаю, что изобретать велосипед - хорошая идея, особенно когда у вас квадратное колесо. Вместо этого вы должны использовать HTMLEncode.
Kramii