Як перетворити HTML у звичайний текст?


98

У мене є фрагменти 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 у звичайний текст .
Джонатан Вуд,

Це була правильна відповідь на те, що мені потрібно - дякую!
Шауль Бер

Є кілька хороших пропозицій від W3C тут: w3.org/Tools/html2things.html
Rich

4
Як питання можна позначити як дублікат запитання, яке було задано через 6 місяців? Здається трохи відсталим ...
Стюарт Гельвіг,

Відповіді:


27

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

<[^>]*>

Якщо вам доведеться турбуватися про <script>теги тощо, вам знадобиться щось потужніше, ніж регулярні вирази, тому що вам потрібно відстежувати стан, щось більше схоже на Context Free Grammar (CFG). Думаючи, що ви зможете досягти цього за допомогою "Зліва направо" або не жадібного збігу.

Якщо ви можете використовувати регулярні вирази, то там є багато веб-сторінок з хорошою інформацією:

Якщо вам потрібна більш складна поведінка CFG, я б запропонував скористатися інструментом третьої сторони, на жаль, я не знаю хорошого, щоб рекомендувати.


3
Вам також слід подбати про значення значень атрибутів, коментарі, PI / CDATA у XML та різні поширені деформації у застарілому HTML. Загалом [X] [HT] ML не піддається синтаксичному аналізу з регулярними виразами.
bobince

11
Це жахливий метод зробити це. Правильним способом є синтаксичний аналіз HTML за допомогою lib та обхід dom, що видає лише вміст із білого списку.
usr

2
@usr: Частина, на яку ви посилаєтесь, є частиною відповіді на CFG. Regex можна використовувати для швидкого і брудного видалення міток, він має свої слабкі сторони, але швидко і легко. Для більш складного аналізу використовуйте інструмент на основі CFG (по-вашому, lib, який генерує DOM). Я не проводив тести, але я б поклав ставку на те, що синтаксичний аналіз DOM відбувається повільніше, ніж видалення регулярних виразів, на випадок, якщо потрібно враховувати продуктивність.
vfilby

1
@vfilby, перша атака, яка спадає на думку, - це написання "<div id = \" "(синтаксис рядка c #). Зверніть увагу на відсутні кінцеві лапки та відсутні фігурні дужки. Я думаю, це заплутає браузер і розбалансує структуру тегів. Ви думаєте про цю атаку? Ви можете бути впевнені, що вона ніколи не спрацює? Неприємно.
usr

1
@vfilby, неважливо, плутається синтаксичний аналіз чи ні. Все, що вам потрібно зробити, це взяти з нього DOM (будь-який DOM взагалі) і вивести лише компоненти з білого списку. Це завжди безпечно, це не має значення, як виглядає проаналізований DOM. Крім того, я розповів вам кілька прикладів, коли ваш "простий" метод не зможе видалити теги.
usr

95

Безкоштовний HtmlAgilityPack із відкритим кодом містить в одному зі своїх зразків метод, який перетворює HTML у звичайний текст.

var plainText = HtmlUtilities.ConvertToPlainText(string html);

Подайте це HTML-рядок, як

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

І ви отримаєте результат простого тексту, такий як:

hello world!

10
Я раніше використовував HtmlAgilityPack, але я не бачу жодного посилання на ConvertToPlainText. Ви можете сказати мені, де я його можу знайти?
Гораціо

8
Гораціо, він включений в один із зразків, який постачається з HtmlAgilityPack: htmlagilitypack.codeplex.com/sourcecontrol/changeset/view/…
Judah Gabriel Himango

5
Насправді, в Agility Pack для цього немає вбудованого методу. Те, до чого ви зв’язали, - це приклад, який використовує Agility Pack для обходу дерева вузлів, видалення scriptта styleтегів та запису внутрішнього тексту інших елементів у вихідний рядок. Я сумніваюся, що це пройшло багато випробувань із реальними входами.
Лу 02

3
Чи може хтось надати код, який працює, на відміну від посилань на зразки, які потребують модернізації для належної роботи?
Eric K

5
Зразок тепер можна знайти тут: 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; було проаналізовано, тому я перемістив текст = System.Net.WebUtility.HtmlDecode (текст); до кінця методу
Луук,

1
Це було чудово, я також додав багатопросторовий конденсатор, оскільки html міг бути створений із системи управління вмістом: var spaceRegex = new Regex ("[] {2,}", RegexOptions.None);
Енкоде

Десь у коді html є новий рядок кодера (новий рядок не можна побачити в коментарі, тому я показую його за допомогою [новий рядок], наприклад: <br> Я [новий рядок] пропускаю [новий рядок] ви <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 застарілий і не підтримує html5
abzarak

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 у звичайний текст

Спочатку потрібно встановити пакет 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);

Чи можу я пропустити перетворення посилань у HTML - -. мені потрібно зберігати посилання в html при перетворенні в текст?
coder771,

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

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

Я думаю, що найпростіший спосіб - це зробити метод розширення "string" (на основі того, що запропонував користувач Річард):

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, "");
        }
}

Тоді просто використовуйте цей метод розширення для будь-якої змінної 'string' у вашій програмі:

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 (), можливо, у вас є щось подібне
markus

"використовувати регулярний вираз" НІ! Це буде чорний список. Ви можете бути в безпеці, лише роблячи білий список. Наприклад, чи ви пам'ятали, що атрибут стилю може містити "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, спочатку потрібно було видалити, оскільки вони спричиняють припинення роботи регулярних виразів, як очікувалося.

Більше того, щоб правильно відображати рядок результатів у текстовому полі, можливо, доведеться розділити його та встановити властивість Рядки текстового поля замість того, щоб присвоювати властивість Текст.

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

Джерело: https://www.codeproject.com/Articles/11902/Convert-HTML-to-Plain-Text-2


0

Залежить від того, що ви маєте на увазі під "html". Найбільш складною справою були б цілі веб-сторінки. Це також найпростіше впоратися, оскільки ви можете використовувати веб-браузер у текстовому режимі. Див. Статтю Вікіпедії із переліком веб-браузерів, включаючи браузери текстового режиму. Рись, мабуть, найвідоміша, але одна з інших може бути кращою для ваших потреб.


як він сказав: "У мене в таблиці зберігаються фрагменти 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;
}

0

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

Як і в кожному запропонованому рішенні, є деякі припущення з кодом нижче:

  • Теги сценарію або стилю не повинні містити теги сценарію та стилю як частину сценарію
  • лише основні вбудовані елементи будуть введені без пробілу, тобто he<span>ll</span>oповинні виводитись hello. Список вбудованих тегів: https://www.w3schools.com/htmL/html_blocks.asp

Враховуючи вищевикладене, наступне розширення рядка зі скомпільованими регулярними виразами виведе очікуваний звичайний текст з урахуванням HTML-екранованих символів та значення 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.
Крамії
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.