Comment convertir du HTML en texte brut?

98

J'ai des extraits de code HTML stockés dans une table. Pas de pages entières, pas de balises ou autres, juste un formatage de base.

Je voudrais pouvoir afficher ce Html sous forme de texte uniquement, sans mise en forme , sur une page donnée (en fait, juste les 30 à 50 premiers caractères, mais c'est le plus facile).

Comment placer le "texte" dans ce HTML dans une chaîne sous forme de texte simple?

Donc ce morceau de code.

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

Devient:

Bonjour le monde. Y a-t-il quelqu'un là-bas?

Stuart Helwig
la source
Vous souhaiterez peut-être utiliser SgmlReader. code.msdn.microsoft.com/SgmlReader
Leonardo Herrera
Il existe un code assez simple et direct pour convertir du HTML en texte brut sur blackbeltcoder.com/Articles/strings/convert-html-to-text .
Jonathan Wood
C'était la bonne réponse pour ce dont j'avais besoin - merci!
Shaul Behr
Il y a quelques bonnes suggestions du W3C ici: w3.org/Tools/html2things.html
Rich
4
Comment marquer une question comme un double d'une question posée 6 mois plus tard? Semble un peu en arrière ...
Stuart Helwig

Réponses:

28

Si vous parlez de suppression de balises, c'est relativement simple si vous n'avez pas à vous soucier de choses comme les <script>balises. Si tout ce que vous avez à faire est d'afficher le texte sans les balises, vous pouvez le faire avec une expression régulière:

<[^>]*>

Si vous devez vous soucier des <script>balises et autres, vous aurez besoin de quelque chose d'un peu plus puissant que les expressions régulières car vous devez suivre l'état, quelque chose qui ressemble plus à une grammaire sans contexte (CFG). Bien que vous puissiez peut-être l'accomplir avec une correspondance «de gauche à droite» ou non gourmande.

Si vous pouvez utiliser des expressions régulières, il existe de nombreuses pages Web avec de bonnes informations:

Si vous avez besoin du comportement plus complexe d'un CFG, je suggérerais d'utiliser un outil tiers, malheureusement je n'en connais pas de bon à recommander.

vfilby
la source
3
Vous devez également vous préoccuper> des valeurs d'attribut, des commentaires, des PI / CDATA en XML et de diverses malformations courantes dans le HTML hérité. En général, [X] [HT] ML ne peut pas être analysé avec des expressions rationnelles.
bobince
11
C'est une méthode terrible pour le faire. La bonne façon est d'analyser le HTML avec une lib et de parcourir le dom en ne sortant que du contenu sur liste blanche.
usr
2
@usr: La partie à laquelle vous faites référence est la partie CFG de la réponse. Regex peut être utilisé pour un décapage rapide et sale des étiquettes, il a ses faiblesses mais il est rapide et facile. Pour une analyse plus compliquée, utilisez un outil basé sur CFG (dans votre langage, une bibliothèque qui génère un DOM). Je n'ai pas effectué les tests, mais je parierais que l'analyse DOM est plus lente que le décapage des regex, au cas où les performances devraient être prises en compte.
vfilby
1
@vfilby, la première attaque qui me vient à l'esprit est l'écriture de "<div id = \" "(syntaxe de chaîne c #). Notez les guillemets manquants et l'accolade fermante manquante. Je suppose que cela va confondre le navigateur et déséquilibrer la structure des balises. Vous pensez à cette attaque? Pouvez-vous être sûr que cela ne fonctionnera jamais? Nasty.
usr
1
@vfilby, peu importe si la bibliothèque d'analyse est confuse ou non. Tout ce que vous avez à faire est d'en extraire le DOM (n'importe quel DOM) et de ne sortir que les composants de la liste blanche. C'est toujours sûr, peu importe à quoi ressemble le DOM analysé. De plus, je vous ai dit plusieurs exemples où votre méthode "simple" échouera à supprimer les balises.
usr
95

Le HtmlAgilityPack gratuit et open source a dans l'un de ses exemples une méthode qui convertit du HTML en texte brut.

var plainText = HtmlUtilities.ConvertToPlainText(string html);

Donnez-lui une chaîne HTML comme

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

Et vous obtiendrez un résultat en texte brut comme:

hello world!
Judah Gabriel Himango
la source
10
J'ai déjà utilisé HtmlAgilityPack mais je ne vois aucune référence à ConvertToPlainText. Pouvez-vous me dire où je peux le trouver?
horatio
8
Horatio, il est inclus dans l'un des échantillons fournis avec HtmlAgilityPack: htmlagilitypack.codeplex.com/sourcecontrol/changeset/view/…
Judah Gabriel Himango
5
En fait, il n'y a pas de méthode intégrée pour cela dans le pack Agility. Ce à quoi vous avez lié est un exemple qui utilise le pack d'agilité pour parcourir l'arborescence des nœuds, supprimer scriptet stylebalises et écrire le texte interne d'autres éléments dans la chaîne de sortie. Je doute qu'il ait passé beaucoup de tests avec des entrées du monde réel.
Lou le
3
Quelqu'un peut-il s'il vous plaît fournir un code qui fonctionne, par opposition à des liens vers des échantillons qui doivent être modernisés pour fonctionner correctement?
Eric K
5
L'exemple peut maintenant être trouvé ici: github.com/ceee/ReadSharp/blob/master/ReadSharp/…
StuartQ
51

Je ne pouvais pas utiliser HtmlAgilityPack, j'ai donc écrit une deuxième meilleure solution pour moi-même

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
la source
2
& lt; blabla & gt; a été analysé, j'ai donc déplacé le texte = System.Net.WebUtility.HtmlDecode (texte); vers le bas de la méthode
Luuk
1
C'était génial, j'ai également ajouté un condensateur multispace car le html aurait pu être généré à partir d'un CMS: var spaceRegex = new Regex ("[] {2,}", RegexOptions.None);
Enkode
Parfois, dans le code html, il y a la nouvelle ligne du codeur (la nouvelle ligne ne peut pas être vue dans le commentaire, donc je la montre avec [nouvelle ligne], comme: <br> Je [nouvelle ligne] manque [nouvelle ligne] vous <br >, Donc il suppose de montrer: "Tu me manques", mais cela montre que je [nouvelle ligne] vous manque [nouvelle ligne]. Cela rend le texte brut douloureux. Savez-vous comment réparer?
123iamking
@ 123iamking vous pouvez utiliser ceci avant de renvoyer le texte; : text.Replace ("[nouvelle ligne]", "\ n");
Eslam Badawy
J'utilisais ceci et je me suis rendu compte qu'il laisse parfois «>» au début des chaînes. L'autre solution d'application de regex <[^>] *> fonctionne très bien.
Etienne Charland
20

HTTPUtility.HTMLEncode()est destiné à gérer le codage des balises HTML sous forme de chaînes. Il s'occupe de tout le travail lourd pour vous. À partir de la documentation MSDN :

Si des caractères tels que des blancs et des signes de ponctuation sont transmis dans un flux HTTP, ils peuvent être mal interprétés à la réception. Le codage HTML convertit les caractères qui ne sont pas autorisés dans HTML en équivalents d'entité de caractère; Le décodage HTML inverse l'encodage. Par exemple, lorsqu'ils sont incorporés dans un bloc de texte, les caractères <et >, sont codés comme &lt;et &gt;pour la transmission HTTP.

HTTPUtility.HTMLEncode()méthode, détaillée ici :

public static void HtmlEncode(
  string s,
  TextWriter output
)

Usage:

String TestString = "This is a <Test String>.";
StringWriter writer = new StringWriter();
Server.HtmlEncode(TestString, writer);
String EncodedString = writer.ToString();
George Stocker
la source
Une très bonne réponse George merci, cela a également souligné à quel point j'ai mal posé la question la première fois. Désolé.
Stuart Helwig
html agility pack est
obsolète
10

Pour ajouter à la réponse de vfilby, vous pouvez simplement effectuer un remplacement RegEx dans votre code; aucune nouvelle classe n'est nécessaire. Au cas où d'autres débutants comme moi tomberaient sur cette question.

using System.Text.RegularExpressions;

Ensuite...

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
la source
19
PAS BON! Cela peut être trompé pour contenir le script en omettant le crochet de fermeture. Les gars, ne faites jamais de liste noire. Vous ne pouvez pas nettoyer les entrées par une liste noire. C'est tellement faux.
usr
7

Processus en trois étapes pour convertir du HTML en texte brut

Vous devez d'abord installer le package Nuget pour HtmlAgilityPack, puis créer cette 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;
        }
    }
}

En utilisant la classe ci-dessus en référence à la réponse de Judah Himango

Troisièmement, vous devez créer l'objet de la classe ci-dessus et utiliser la ConvertHtml(HTMLContent)méthode pour convertir le HTML en texte brut plutôt queConvertToPlainText(string html);

HtmlToText htt=new HtmlToText();
var plainText = htt.ConvertHtml(HTMLContent);
Abdulqadir_WDDN
la source
puis-je ignorer la conversion des liens en html. dois-je conserver des liens en HTML lors de la conversion en texte?
coder771
6

Il a une limitation qui ne réduit pas les longs espaces blancs en ligne, mais il est définitivement portable et respecte la mise en page comme le navigateur 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
la source
4

Il n'y a pas de méthode avec le nom 'ConvertToPlainText' dans le HtmlAgilityPack mais vous pouvez convertir une chaîne html en chaîne CLEAR avec:

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

Cela fonctionne pour moi. MAIS JE NE TROUVE PAS DE MÉTHODE AVEC LE NOM «ConvertToPlainText» DANS «HtmlAgilityPack».

Amine
la source
3

Je pense que le moyen le plus simple est de créer une méthode d'extension `` chaîne '' (basée sur ce que l'utilisateur Richard a suggéré):

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

Ensuite, utilisez simplement cette méthode d'extension sur n'importe quelle variable 'chaîne' de votre programme:

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

J'utilise cette méthode d'extension pour convertir les commentaires au format HTML en texte brut afin qu'ils s'affichent correctement sur un rapport Crystal, et cela fonctionne parfaitement!

mikhail-t
la source
3

Le moyen le plus simple que j'ai trouvé:

HtmlFilter.ConvertToPlainText(html);

La classe HtmlFilter se trouve dans Microsoft.TeamFoundation.WorkItemTracking.Controls.dll

La dll se trouve dans un dossier comme celui-ci:% ProgramFiles% \ Common Files \ microsoft shared \ Team Foundation Server \ 14.0 \

Dans VS 2015, la dll nécessite également une référence à Microsoft.TeamFoundation.WorkItemTracking.Common.dll, situé dans le même dossier.

O romain
la source
prend-il soin des balises de script et est-il formaté en italique gras, etc.?
Samra
Présentation d'une dépendance de fondation d'équipe pour la conversion de HTML en texte brut, très discutable ...
ViRuSTriNiTy
2

Si vous avez des données contenant des balises HTML et que vous souhaitez les afficher pour qu'une personne puisse VOIR les balises, utilisez HttpServerUtility :: HtmlEncode.

Si vous avez des données contenant des balises HTML et que vous souhaitez que l'utilisateur voie les balises rendues, affichez le texte tel quel. Si le texte représente une page Web entière, utilisez un IFRAME pour cela.

Si vous avez des données contenant des balises HTML et que vous souhaitez supprimer les balises et afficher simplement le texte non formaté, utilisez une expression régulière.

Corey Trager
la source
en php il y a une fonction appelée striptags () peut-être avez-vous quelque chose de similaire
markus
"utiliser une expression régulière" NON! Ce serait une liste noire. Vous ne pouvez être sûr que de faire une liste blanche. Par exemple, vous êtes-vous souvenu que l'attibute de style peut contenir "background: url ('javascript: ...');"? bien sûr que non, je ne l'aurais pas non plus. C'est pourquoi la liste noire ne fonctionne pas.
usr
2

J'ai rencontré un problème similaire et j'ai trouvé la meilleure solution. Le code ci-dessous fonctionne parfaitement pour moi.

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

}

Les caractères d'échappement tels que \ n et \ r ont dû être supprimés en premier car ils empêchent les expressions régulières de fonctionner comme prévu.

De plus, pour que la chaîne de résultat s'affiche correctement dans la zone de texte, il peut être nécessaire de la diviser et de définir la propriété Lines de la zone de texte au lieu de l'affecter à la propriété Text.

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

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

LakshmiSarada
la source
0

Cela dépend de ce que vous entendez par «html». Le cas le plus complexe serait celui des pages Web complètes. C'est également le plus simple à gérer, car vous pouvez utiliser un navigateur Web en mode texte. Consultez l'article Wikipédia répertoriant les navigateurs Web, y compris les navigateurs en mode texte. Lynx est probablement le plus connu, mais l'un des autres peut être meilleur pour vos besoins.

mpez0
la source
comme il l'a dit: "J'ai des extraits de code HTML stockés dans une table."
M le
0

Voici ma solution:

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

Exemple:

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

J'avais la même question, juste mon html avait une mise en page simple pré-connue, comme:

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

J'ai donc fini par utiliser un code aussi simple:

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

Quelles sorties:

abc
def
Karlas
la source
0

N'a pas écrit mais une utilisation:

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
la source
0

Je pense qu'il a une réponse simple:

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

Pour tous ceux qui recherchent une solution exacte à la question OP pour une abréviation textuelle d'un document html donné, sans nouvelles lignes ni balises HTML, veuillez trouver la solution ci-dessous.

Comme pour toute solution proposée, il y a quelques hypothèses avec le code ci-dessous:

  • Les balises de script ou de style ne doivent pas contenir de balises de script et de style dans le cadre du script
  • seuls les principaux éléments en ligne seront insérés sans espace, c'est-à-dire qu'ils he<span>ll</span>odevraient être affichés hello. Liste des balises en ligne: https://www.w3schools.com/htmL/html_blocks.asp

Compte tenu de ce qui précède, l'extension de chaîne suivante avec des expressions régulières compilées produira le texte brut attendu en ce qui concerne les caractères d'échappement html et null sur une entrée nulle.

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);
}
aussi
la source
-4

chaîne statique publique StripTags2 (string html) {return html.Replace ("<", "<"). Replace (">", ">"); }

Par cela, vous évitez tous les "<" et ">" dans une chaîne. c'est ce que tu veux?

José Leal
la source
... ah. Eh bien maintenant, la réponse (ainsi que l'interprétation de la question ambiguë) a complètement changé, je vais choisir des lentes à l'absence de & amp; encodage à la place. ;-)
bobince
2
Je ne pense pas que ce soit une bonne idée de réinventer la roue - surtout lorsque votre roue est carrée. Vous devez utiliser HTMLEncode à la place.
Kramii