Como você converte Html em texto simples?

98

Tenho trechos de Html armazenados em uma tabela. Não páginas inteiras, sem tags ou similares, apenas formatação básica.

Gostaria de poder exibir esse Html apenas como texto, sem formatação , em uma determinada página (na verdade, apenas os primeiros 30 a 50 caracteres, mas essa é a parte fácil).

Como coloco o "texto" dentro desse Html em uma string como texto simples?

Então, este pedaço de código.

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

Torna-se:

Olá Mundo. Tem alguém aí fora?

Stuart Helwig
fonte
Você pode querer usar SgmlReader. code.msdn.microsoft.com/SgmlReader
Leonardo Herrera
Há um código bastante simples e direto para converter HTML em texto simples em blackbeltcoder.com/Articles/strings/convert-html-to-text .
Jonathan Wood,
Essa foi a resposta certa para o que eu precisava - obrigado!
Shaul Behr
Há algumas boas sugestões do W3C aqui: w3.org/Tools/html2things.html
Rich
4
Como uma pergunta pode ser marcada como duplicata de uma pergunta feita 6 meses depois? Parece um pouco para trás ...
Stuart Helwig

Respostas:

27

Se você está falando sobre remoção de tags, é relativamente simples se você não precisa se preocupar com coisas como <script>tags. Se tudo o que você precisa fazer é exibir o texto sem as tags, você pode fazer isso com uma expressão regular:

<[^>]*>

Se você tiver que se preocupar com <script>tags e similares, então você precisará de algo um pouco mais poderoso do que as expressões regulares, porque você precisa rastrear o estado, algo mais como uma Gramática Livre de Contexto (CFG). Embora você possa conseguir isso com 'Da esquerda para a direita' ou correspondência não gananciosa.

Se você pode usar expressões regulares, existem muitas páginas da web por aí com boas informações:

Se você precisa do comportamento mais complexo de um CFG, eu sugeriria o uso de uma ferramenta de terceiros, infelizmente não conheço uma boa para recomendar.

vfilby
fonte
3
Você também precisa se preocupar com> em valores de atributo, comentários, PIs / CDATA em XML e vários defeitos comuns em HTML legado. Em geral, [X] [HT] ML não pode ser analisado com regexps.
bobince
11
Este é um método terrível de fazer isso. A maneira correta é analisar o HTML com uma lib e percorrer o dom gerando apenas o conteúdo da lista de permissões.
usr
2
@usr: A parte a que você está se referindo é a parte CFG da resposta. Regex pode ser usado para a remoção rápida e suja de etiquetas, tem seus pontos fracos, mas é rápido e fácil. Para uma análise mais complicada, use uma ferramenta baseada em CFG (em sua linguagem, uma biblioteca que gera um DOM). Não realizei os testes, mas aposto que a análise DOM é mais lenta do que a remoção de regex, caso o desempenho precise ser considerado.
vfilby
1
@vfilby, o primeiro ataque que vem à mente é escrever "<div id = \" "(sintaxe de string c #). Observe as aspas finais ausentes e a chave de fechamento ausente. Acho que isso vai confundir o navegador e desequilibrar a estrutura da tag. Você pensa neste ataque? Pode ter certeza de que nunca funciona? Desagradável.
usr
1
@vfilby, não importa se a biblioteca de análise é confusa ou não. Tudo o que você precisa fazer é tirar o DOM dele (qualquer DOM) e gerar apenas os componentes da lista de permissões. Isso é sempre seguro, não importa a aparência do DOM analisado. Além disso, eu disse a você vários exemplos em que seu método "simples" não conseguirá remover tags.
usr
95

O HtmlAgilityPack gratuito e de código aberto tem em uma de suas amostras um método que converte HTML em texto simples.

var plainText = HtmlUtilities.ConvertToPlainText(string html);

Alimente-o com uma string HTML como

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

E você obterá um resultado de texto simples como:

hello world!
Judah Gabriel Himango
fonte
10
Já usei HtmlAgilityPack antes, mas não consigo ver nenhuma referência a ConvertToPlainText. Você pode me dizer onde posso encontrá-lo?
horatio
8
Horatio, está incluído em uma das amostras que vem com o HtmlAgilityPack: htmlagilitypack.codeplex.com/sourcecontrol/changeset/view/…
Judah Gabriel Himango
5
Na verdade, não existe um método integrado para isso no Agility Pack. Você vinculou a um exemplo que usa o Agility Pack para percorrer a árvore de nós, remover scripte stylemarcar e escrever o texto interno de outros elementos na string de saída. Duvido que tenha passado muitos testes com entradas do mundo real.
Lou,
3
Alguém pode fornecer um código que funcione, em vez de links para exemplos que precisam ser adaptados para funcionar corretamente?
Eric K,
5
O exemplo agora pode ser encontrado aqui: github.com/ceee/ReadSharp/blob/master/ReadSharp/…
StuartQ
51

Não consegui usar o HtmlAgilityPack, então escrevi uma segunda melhor solução para mim

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;
}
Ben Anderson
fonte
2
& lt; blabla & gt; foi analisado, então movi o text = System.Net.WebUtility.HtmlDecode (text); ao final do método
Luuk de
1
Isso foi ótimo, também adicionei um condensador multispace, pois o html pode ter sido gerado a partir de um CMS: var spaceRegex = new Regex ("[] {2,}", RegexOptions.None);
Enkode
Às vezes, no código html há uma nova linha do codificador (a nova linha não pode ser vista no comentário, então eu a mostro com [nova linha], como: <br> I [nova linha] sinto falta [nova linha] você <br >, Suponho que mostre: "Sinto sua falta", mas mostra que eu [nova linha] sinto sua falta [nova linha]. Isso faz com que o texto simples pareça doloroso. Você sabe como consertar?
123iamking
@ 123iamking você pode usar isto antes de retornar o texto; : text.Replace ("[nova linha]", "\ n");
Eslam Badawy,
Eu estava usando isso e percebi que às vezes sai '>' no início das cordas. A outra solução de aplicação de regex <[^>] *> funciona bem.
Etienne Charland
20

HTTPUtility.HTMLEncode()destina-se a lidar com a codificação de tags HTML como strings. Ele cuida de todo o trabalho pesado para você. Da documentação do MSDN :

Se caracteres como espaços em branco e pontuação forem passados ​​em um fluxo HTTP, eles podem ser mal interpretados na extremidade receptora. A codificação HTML converte caracteres que não são permitidos em HTML em equivalentes de entidade de caractere; A decodificação HTML reverte a codificação. Por exemplo, quando embutidos em um bloco de texto, os caracteres <e >, são codificados como &lt;e &gt;para transmissão HTTP.

HTTPUtility.HTMLEncode()método, detalhado aqui :

public static void HtmlEncode(
  string s,
  TextWriter output
)

Uso:

String TestString = "This is a <Test String>.";
StringWriter writer = new StringWriter();
Server.HtmlEncode(TestString, writer);
String EncodedString = writer.ToString();
George Stocker
fonte
Uma resposta muito boa, George, obrigado, também destacou o quão mal eu fiz a pergunta na primeira vez. Desculpe.
Stuart Helwig
O pacote de agilidade html está desatualizado e não é compatível com html5
abzarak
10

Para adicionar à resposta de vfilby, você pode apenas realizar uma substituição RegEx em seu código; nenhuma nova classe é necessária. No caso de outros novatos como eu tropeçar nesta questão.

using System.Text.RegularExpressions;

Então...

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
fonte
19
NÃO É BOM! Isso pode ser enganado para conter o script, omitindo o colchete angular de fechamento. GAROTOS, nunca façam listas negras. Você não pode limpar a entrada pela lista negra. Isto é tão errado.
usr
7

Processo de três etapas para converter HTML em texto simples

Primeiro, você precisa instalar o pacote Nuget para HtmlAgilityPack. Segundo, criar esta classe

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

Usando a classe acima com referência à resposta de Judah Himango

Terceiro, você precisa criar o objeto da classe acima e usar o ConvertHtml(HTMLContent)método para converter HTML em texto simples em vez deConvertToPlainText(string html);

HtmlToText htt=new HtmlToText();
var plainText = htt.ConvertHtml(HTMLContent);
Abdulqadir_WDDN
fonte
posso pular links de conversão em html. eu preciso manter links em html ao converter para texto?
coder771
6

Ele tem a limitação de não recolher longos espaços em branco embutidos, mas é definitivamente portátil e respeita o layout como o navegador da 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;
}
Jeiea
fonte
4

Não existe um método com o nome 'ConvertToPlainText' no HtmlAgilityPack, mas você pode converter uma string html em string CLEAR com:

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

Isso funciona para mim. MAS NÃO ENCONTREI UM MÉTODO COM O NOME 'ConvertToPlainText' EM 'HtmlAgilityPack'.

Amine
fonte
3

Acho que a maneira mais fácil é fazer um método de extensão de 'string' (com base no que o usuário Richard sugeriu):

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

Em seguida, use este método de extensão em qualquer variável 'string' em seu programa:

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

Eu uso este método de extensão para converter comentários formatados em html em texto simples para que sejam exibidos corretamente em um Crystal Report e funciona perfeitamente!

Mikhail-t
fonte
3

A maneira mais simples que encontrei:

HtmlFilter.ConvertToPlainText(html);

A classe HtmlFilter está localizada em Microsoft.TeamFoundation.WorkItemTracking.Controls.dll

A dll pode ser encontrada em uma pasta como esta:% ProgramFiles% \ Common Files \ microsoft shared \ Team Foundation Server \ 14.0 \

No VS 2015, a dll também requer referência a Microsoft.TeamFoundation.WorkItemTracking.Common.dll, localizado na mesma pasta.

Roman O
fonte
ele cuida das tags de script e formata como negrito itálico etc?
Samra
Apresentando uma dependência de base de equipe para converter html em texto simples, muito questionável ...
ViRuSTriNiTy
2

Se você tiver dados com tags HTML e quiser exibi-los para que uma pessoa possa VER as tags, use HttpServerUtility :: HtmlEncode.

Se você tiver dados com tags HTML e quiser que o usuário veja as tags renderizadas, exiba o texto como está. Se o texto representar uma página da web inteira, use um IFRAME para isso.

Se você tiver dados com tags HTML e desejar remover as tags e apenas exibir o texto não formatado, use uma expressão regular.

Corey Trager
fonte
no php existe uma função chamada striptags () talvez você tenha algo semelhante
markus
"usar uma expressão regular" NÃO! Isso seria uma lista negra. Você só pode estar seguro fazendo whitelisting. Por exemplo, você deve ter se lembrado de que o atributo de estilo pode conter "background: url ('javascript: ...');"? claro que não, eu também não. É por isso que a lista negra não funciona.
usr
2

Eu enfrentei problema semelhante e encontrei a melhor solução. O código abaixo funciona perfeitamente para mim.

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

}

Caracteres de escape, como \ n e \ r, tiveram que ser removidos primeiro porque fazem com que as regexes parem de funcionar conforme o esperado.

Além disso, para fazer a string de resultado ser exibida corretamente na caixa de texto, pode ser necessário dividi-la e definir a propriedade Lines da caixa de texto em vez de atribuir à propriedade Text.

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

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

LakshmiSarada
fonte
0

Depende do que você entende por "html". O caso mais complexo seria páginas da web completas. Isso também é o mais fácil de lidar, já que você pode usar um navegador da Web em modo texto. Consulte o artigo da Wikipedia que lista navegadores da web, incluindo navegadores em modo de texto. Lynx é provavelmente o mais conhecido, mas um dos outros pode ser melhor para suas necessidades.

mpez0
fonte
como ele disse "Eu tenho trechos de Html armazenados em uma tabela."
M em
0

Aqui está minha solução:

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

Exemplo:

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

Eu tive a mesma dúvida, só que meu html tinha um layout simples e pré-conhecido, como:

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

Então, acabei usando um código tão simples:

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

Quais saídas:

abc
def
Karlas
fonte
0

Não escrevi, mas usando:

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 };
    }
  }
}
sobelito
fonte
0

Acho que tem uma resposta simples:

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

Para quem procura uma solução exata para a questão do OP para uma abreviação textual de um determinado documento html, sem novas linhas e tags HTML, encontre a solução abaixo.

Como com toda solução proposta, existem algumas suposições com o código abaixo:

  • script ou tags de estilo não devem conter tags de script e estilo como parte do script
  • apenas os principais elementos embutidos serão embutidos sem espaço, ou seja, he<span>ll</span>odevem ser impressos hello. Lista de tags inline: https://www.w3schools.com/htmL/html_blocks.asp

Considerando o acima, a seguinte extensão de string com expressões regulares compiladas produzirá o texto simples esperado em relação aos caracteres html com escape e nulo na entrada nula.

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);
}
também
fonte
-4

string pública estática StripTags2 (string html) {return html.Replace ("<", "<"). Replace (">", ">"); }

Com isso, você escapa todos os "<" e ">" em uma string. É isso que voce quer?

José Leal
fonte
... ah. Bem, agora a resposta (junto com a interpretação da pergunta ambígua) mudou completamente, vou pegar no pé da falta de & amp; codificação em vez disso. ;-)
bobince
2
Não acho uma boa ideia reinventar a roda - especialmente quando ela é quadrada. Você deve usar HTMLEncode em vez disso.
Kramii