Wie konvertiert man HTML in einfachen Text?

98

Ich habe HTML-Schnipsel in einer Tabelle gespeichert. Nicht ganze Seiten, keine Tags oder ähnliches, nur einfache Formatierung.

Ich möchte in der Lage sein, diesen HTML-Code nur als Text ohne Formatierung auf einer bestimmten Seite anzuzeigen (eigentlich nur die ersten 30 - 50 Zeichen, aber das ist das einfache Stück).

Wie platziere ich den "Text" in diesem HTML-Code in einer Zeichenfolge als geraden Text?

Also dieser Code.

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

Wird:

Hallo Welt. Gibt es da draußen jemanden?

Stuart Helwig
quelle
Möglicherweise möchten Sie SgmlReader verwenden. code.msdn.microsoft.com/SgmlReader
Leonardo Herrera
Unter blackbeltcoder.com/Articles/strings/convert-html-to-text gibt es einen ziemlich einfachen und unkomplizierten Code zum Konvertieren von HTML in einfachen Text .
Jonathan Wood
Dies war die richtige Antwort für das, was ich brauchte - danke!
Shaul Behr
Es gibt einige gute Vorschläge vom W3C hier: w3.org/Tools/html2things.html
Rich
4
Wie kann eine Frage als Duplikat einer Frage markiert werden, die 6 Monate später gestellt wurde? Scheint ein wenig rückwärts ...
Stuart Helwig

Antworten:

27

Wenn Sie über das Entfernen von Tags sprechen, ist es relativ einfach, wenn Sie sich nicht um Dinge wie <script>Tags kümmern müssen . Wenn Sie nur den Text ohne die Tags anzeigen müssen, können Sie dies mit einem regulären Ausdruck erreichen:

<[^>]*>

Wenn Sie sich um <script>Tags und ähnliches kümmern müssen, benötigen Sie etwas Stärkeres als reguläre Ausdrücke, da Sie den Status verfolgen müssen, was eher einer kontextfreien Grammatik (CFG) ähnelt. Obwohl Sie dies möglicherweise mit "Left To Right" oder nicht gierigem Matching erreichen können.

Wenn Sie reguläre Ausdrücke verwenden können, gibt es viele Webseiten mit guten Informationen:

Wenn Sie das komplexere Verhalten einer CFG benötigen, würde ich die Verwendung eines Tools eines Drittanbieters vorschlagen. Leider kenne ich kein gutes Tool, das ich empfehlen kann.

vfilby
quelle
3
Sie müssen sich auch um Attributwerte, Kommentare, PIs / CDATA in XML und verschiedene häufige Fehler in altem HTML kümmern. Im Allgemeinen kann [X] [HT] ML nicht mit regulären Ausdrücken analysiert werden.
Bobince
11
Dies ist eine schreckliche Methode, um es zu tun. Der richtige Weg ist, den HTML-Code mit einer Bibliothek zu analysieren und den Dom zu durchlaufen, der nur Inhalte auf der Whitelist ausgibt.
usr
2
@usr: Der Teil, auf den Sie sich beziehen, ist der CFG-Teil der Antwort. Regex kann zum schnellen und schmutzigen Entfernen von Tags verwendet werden. Es hat seine Schwächen, ist aber schnell und einfach. Verwenden Sie für eine kompliziertere Analyse ein CFG-basiertes Tool (in Ihrer Sprache eine Bibliothek, die ein DOM generiert). Ich habe die Tests nicht durchgeführt, aber ich würde wetten, dass das Parsen von DOM langsamer ist als das Entfernen von Regex, falls die Leistung berücksichtigt werden muss.
Vfilby
1
@vfilby, der erste Angriff, der mir in den Sinn kommt, ist das Schreiben von "<div id = \" "(c # -String-Syntax). Beachten Sie die fehlenden Anführungszeichen und die fehlende schließende Klammer. Ich denke, dies wird den Browser verwirren und die Tag-Struktur aus dem Gleichgewicht bringen Sie denken an diesen Angriff? Können Sie sicher sein, dass er nie funktioniert? Böse.
usr
1
@vfilby, es spielt keine Rolle, ob die Parsing-Bibliothek verwirrt ist oder nicht. Alles, was Sie tun müssen, ist, das DOM daraus zu nehmen (überhaupt ein DOM) und nur Komponenten auf der Whitelist auszugeben. Dies ist immer sicher, es spielt keine Rolle, wie das analysierte DOM aussieht. Außerdem habe ich Ihnen mehrere Beispiele genannt, bei denen Ihre "einfache" Methode keine Tags entfernen kann.
usr
95

Das kostenlose und Open-Source- HtmlAgilityPack verfügt in einem seiner Beispiele über eine Methode, die HTML in einfachen Text konvertiert.

var plainText = HtmlUtilities.ConvertToPlainText(string html);

Füttere es wie eine HTML-Zeichenfolge

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

Und Sie erhalten ein einfaches Textergebnis wie:

hello world!
Judah Gabriel Himango
quelle
10
Ich habe HtmlAgilityPack bereits verwendet, kann jedoch keinen Verweis auf ConvertToPlainText sehen. Können Sie mir sagen, wo ich es finden kann?
Horatio
8
Horatio, es ist in einem der Beispiele enthalten, die mit HtmlAgilityPack geliefert werden: htmlagilitypack.codeplex.com/sourcecontrol/changeset/view/…
Judah Gabriel Himango
5
Tatsächlich gibt es dafür im Agility Pack keine integrierte Methode. Was Sie verlinkt haben, ist ein Beispiel, das das Agility Pack verwendet, um den Knotenbaum zu durchlaufen, zu entfernen scriptund zu stylemarkieren und inneren Text anderer Elemente in die Ausgabezeichenfolge zu schreiben. Ich bezweifle, dass es viele Tests mit realen Eingaben bestanden hat.
Lou
3
Kann jemand bitte Code bereitstellen, der funktioniert, im Gegensatz zu Links zu Beispielen, die nachgerüstet werden müssen, um ordnungsgemäß zu funktionieren?
Eric K
5
Das Beispiel kann jetzt hier gefunden werden: github.com/ceee/ReadSharp/blob/master/ReadSharp/…
StuartQ
51

Ich konnte HtmlAgilityPack nicht verwenden, daher habe ich eine zweitbeste Lösung für mich geschrieben

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
quelle
2
& lt; blabla & gt; wurde analysiert, also habe ich den Text verschoben = System.Net.WebUtility.HtmlDecode (Text); auf den Grund der Methode
Luuk
1
Das war großartig, ich habe auch einen Multispace-Kondensator hinzugefügt, da der HTML-Code möglicherweise aus einem CMS generiert wurde: var spaceRegex = new Regex ("[] {2,}", RegexOptions.None);
Enkode
Irgendwann gibt es im HTML-Code die neue Zeile des Codierers (neue Zeile ist im Kommentar nicht zu sehen, daher zeige ich sie mit [neue Zeile], wie: <br> Ich [neue Zeile] vermisse [neue Zeile] Sie <br >, Es soll also zeigen: "Ich vermisse dich", aber es zeigt, dass ich [neue Zeile] dich vermisse. Dies lässt den Klartext schmerzhaft aussehen. Weißt du, wie man das behebt?
123iamking
@ 123iamking können Sie dies verwenden, bevor Sie Text zurückgeben; : text.Replace ("[neue Zeile]", "\ n");
Eslam Badawy
Ich habe dies verwendet und festgestellt, dass es manchmal '>' am Anfang der Zeichenfolgen hinterlässt. Die andere Lösung zum Anwenden von Regex <[^>] *> funktioniert einwandfrei.
Etienne Charland
20

HTTPUtility.HTMLEncode()soll das Codieren von HTML-Tags als Zeichenfolgen behandeln. Es kümmert sich um all das schwere Heben für Sie. Aus der MSDN-Dokumentation :

Wenn Zeichen wie Leerzeichen und Interpunktion in einem HTTP-Stream übergeben werden, werden sie möglicherweise auf der Empfangsseite falsch interpretiert. Die HTML-Codierung konvertiert Zeichen, die in HTML nicht zulässig sind, in Entitäten von Zeichenentitäten. Die HTML-Dekodierung kehrt die Kodierung um. Wenn sie beispielsweise in einen Textblock eingebettet sind, werden die Zeichen <und >, als &lt;und &gt;für die HTTP-Übertragung codiert .

HTTPUtility.HTMLEncode()Methode, hier detailliert :

public static void HtmlEncode(
  string s,
  TextWriter output
)

Verwendung:

String TestString = "This is a <Test String>.";
StringWriter writer = new StringWriter();
Server.HtmlEncode(TestString, writer);
String EncodedString = writer.ToString();
George Stocker
quelle
Eine wirklich gute Antwort, George, danke, es hat auch deutlich gemacht, wie schlecht ich die Frage beim ersten Mal gestellt habe. Es tut uns leid.
Stuart Helwig
Das HTML Agility Pack ist veraltet und unterstützt kein HTML5
Abzarak
10

Um die Antwort von vfilby zu ergänzen, können Sie einfach einen RegEx-Austausch in Ihrem Code durchführen. Es sind keine neuen Klassen erforderlich. Für den Fall, dass andere Neulinge wie ich über diese Frage stolpern.

using System.Text.RegularExpressions;

Dann...

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
quelle
19
NICHT GUT! Dies kann ausgetrickst werden, um ein Skript zu enthalten, indem die schließende spitze Klammer weggelassen wird. Leute, macht niemals eine schwarze Liste. Sie können Eingaben nicht durch Blacklisting bereinigen. Das ist so falsch.
usr
7

Dreistufiger Prozess zum Konvertieren von HTML in Nur-Text

Zuerst müssen Sie das Nuget-Paket für HtmlAgilityPack installieren. Zweitens müssen Sie diese Klasse erstellen

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

Durch die Verwendung der obigen Klasse in Bezug auf Judah Himangos Antwort

Drittens müssen Sie das Objekt der obigen Klasse und die Verwendungsmethode ConvertHtml(HTMLContent)zum Konvertieren von HTML in einfachen Text anstatt erstellenConvertToPlainText(string html);

HtmlToText htt=new HtmlToText();
var plainText = htt.ConvertHtml(HTMLContent);
Abdulqadir_WDDN
quelle
Kann ich das Konvertieren von Links in HTML überspringen? Ich muss Links in HTML behalten, wenn ich in Text konvertiere?
coder771
6

Es hat die Einschränkung, dass lange Inline-Leerzeichen nicht reduziert werden, aber es ist definitiv portabel und respektiert das Layout wie ein Webbrowser.

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
quelle
4

Es gibt keine Methode mit dem Namen 'ConvertToPlainText' im HtmlAgilityPack, aber Sie können eine HTML-Zeichenfolge in eine CLEAR-Zeichenfolge konvertieren mit:

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

Das funktioniert bei mir. ABER ICH FINDE KEINE METHODE MIT DEM NAMEN 'ConvertToPlainText' IN 'HtmlAgilityPack'.

Amin
quelle
3

Ich denke, der einfachste Weg ist, eine 'String'-Erweiterungsmethode zu erstellen (basierend auf dem, was Benutzer Richard vorgeschlagen hat):

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

Verwenden Sie dann einfach diese Erweiterungsmethode für eine beliebige 'String'-Variable in Ihrem Programm:

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

Ich verwende diese Erweiterungsmethode, um HTML-formatierte Kommentare in einfachen Text umzuwandeln, damit sie in einem Crystal Reports-Bericht korrekt angezeigt werden und perfekt funktionieren!

mikhail-t
quelle
3

Der einfachste Weg, den ich gefunden habe:

HtmlFilter.ConvertToPlainText(html);

Die HtmlFilter-Klasse befindet sich in Microsoft.TeamFoundation.WorkItemTracking.Controls.dll

Die DLL befindet sich in einem Ordner wie dem folgenden:% ProgramFiles% \ Common Files \ Microsoft Shared \ Team Foundation Server \ 14.0 \

In VS 2015 erfordert die DLL auch einen Verweis auf Microsoft.TeamFoundation.WorkItemTracking.Common.dll, das sich im selben Ordner befindet.

Roman O.
quelle
kümmert es sich um Skript-Tags und formatiert es fett kursiv usw.?
Samra
Einführung einer Team Foundation-Abhängigkeit für die Konvertierung von HTML in einfachen Text, sehr fragwürdig ...
ViRuSTriNiTy
2

Wenn Sie Daten mit HTML-Tags haben und diese anzeigen möchten, damit eine Person die Tags sehen kann, verwenden Sie HttpServerUtility :: HtmlEncode.

Wenn Sie Daten mit HTML-Tags haben und der Benutzer die gerenderten Tags sehen soll, zeigen Sie den Text unverändert an. Wenn der Text eine gesamte Webseite darstellt, verwenden Sie einen IFRAME dafür.

Wenn Sie Daten mit HTML-Tags haben und die Tags entfernen und nur den unformatierten Text anzeigen möchten, verwenden Sie einen regulären Ausdruck.

Corey Trager
quelle
in php gibt es eine funktion namens striptags () vielleicht hast du etwas ähnliches
markus
"benutze einen regulären Ausdruck" NEIN! Dies wäre eine schwarze Liste. Sie können nur sicher sein, wenn Sie eine Whitelist durchführen. Hätten Sie sich zum Beispiel daran erinnert, dass das Stilattribut "background: url ('javascript: ...');" enthalten kann? natürlich nicht, hätte ich auch nicht. Deshalb funktioniert Blacklisting nicht.
usr
2

Ich habe mich einem ähnlichen Problem gestellt und die beste Lösung gefunden. Der folgende Code funktioniert perfekt für mich.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

}}

Escape-Zeichen wie \ n und \ r mussten zuerst entfernt werden, da sie dazu führen, dass reguläre Ausdrücke nicht mehr wie erwartet funktionieren.

Um die Ergebniszeichenfolge korrekt im Textfeld anzuzeigen, müssen Sie sie möglicherweise aufteilen und die Lines-Eigenschaft des Textfelds festlegen, anstatt sie der Text-Eigenschaft zuzuweisen.

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

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

LakshmiSarada
quelle
0

Kommt darauf an, was du mit "html" meinst. Der komplexeste Fall wären vollständige Webseiten. Dies ist auch am einfachsten zu handhaben, da Sie einen Webbrowser im Textmodus verwenden können. Weitere Informationen finden Sie im Wikipedia-Artikel mit Webbrowsern, einschließlich Browsern im Textmodus. Lynx ist wahrscheinlich der bekannteste, aber einer der anderen ist möglicherweise besser für Ihre Bedürfnisse.

mpez0
quelle
wie er sagte "Ich habe Ausschnitte von HTML in einer Tabelle gespeichert."
M am
0

Hier ist meine Lösung:

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

Beispiel:

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

Ich hatte die gleiche Frage, nur mein HTML hatte ein einfaches vorbekanntes Layout, wie:

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

Also habe ich so einfachen Code verwendet:

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

Welche Ausgänge:

abc
def
Karlas
quelle
0

Nicht geschrieben, sondern eine Verwendung:

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
quelle
0

Ich denke, es hat eine einfache Antwort:

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

Für alle, die nach einer genauen Lösung für die OP-Frage für eine Textabkürzung eines bestimmten HTML-Dokuments ohne Zeilenumbrüche und HTML-Tags suchen, finden Sie unten die Lösung.

Wie bei jeder vorgeschlagenen Lösung gibt es einige Annahmen mit dem folgenden Code:

  • Skript- oder Stil-Tags sollten keine Skript- und Stil-Tags als Teil des Skripts enthalten
  • Nur wichtige Inline-Elemente werden ohne Leerzeichen eingefügt, dh sie he<span>ll</span>osollten ausgegeben werden hello. Liste der Inline-Tags: https://www.w3schools.com/htmL/html_blocks.asp

In Anbetracht des oben Gesagten gibt die folgende Zeichenfolgenerweiterung mit kompilierten regulären Ausdrücken erwarteten Klartext in Bezug auf HTML-Escapezeichen und Null bei Null-Eingabe aus.

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);
}
auch
quelle
-4

öffentliche statische Zeichenfolge StripTags2 (Zeichenfolge html) {return html.Replace ("<", "<"). Replace (">", ">"); }}

Auf diese Weise entkommen Sie allen "<" und ">" in einer Zeichenfolge. Ist das was du willst?

José Leal
quelle
...Ah. Nun hat sich die Antwort (zusammen mit der Interpretation der mehrdeutigen Frage) vollständig geändert. Ich werde Nissen auswählen, wenn & amp; Codierung stattdessen. ;-)
Bobince
2
Ich denke nicht, dass es eine gute Idee ist, das Rad neu zu erfinden - besonders wenn Ihr Rad quadratisch ist. Sie sollten stattdessen HTMLEncode verwenden.
Kramii