คุณแปลง Html เป็นข้อความธรรมดาได้อย่างไร?


107

ฉันมีตัวอย่างของ Html ที่เก็บไว้ในตาราง ไม่ใช่ทั้งหน้าไม่มีแท็กหรือสิ่งที่ชอบเป็นเพียงการจัดรูปแบบพื้นฐาน

ฉันต้องการที่จะสามารถแสดง Html นั้นเป็นข้อความเท่านั้นไม่มีการจัดรูปแบบในหน้าที่กำหนด (จริงๆแล้วเป็นเพียงอักขระ 30-50 ตัวแรก แต่นั่นเป็นบิตที่ง่าย)

ฉันจะวาง "ข้อความ" ภายใน Html นั้นให้เป็นสตริงเป็นข้อความตรงได้อย่างไร

โค้ดชิ้นนี้

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

กลายเป็น:

สวัสดีชาวโลก. มีใครอยู่ข้างนอกบ้าง?


คุณอาจต้องการใช้ SgmlReader code.msdn.microsoft.com/SgmlReader
Leonardo Herrera

มีบางอย่างง่ายสวยและรหัสตรงไปข้างหน้าการแปลง HTML เป็นข้อความธรรมดาที่เป็นblackbeltcoder.com/Articles/strings/convert-html-to-text
Jonathan Wood

นี่คือคำตอบที่ถูกต้องสำหรับสิ่งที่ฉันต้องการ - ขอบคุณ!
Shaul Behr

มีคำแนะนำดีๆจาก W3C ที่นี่: w3.org/Tools/html2things.html
รวย

4
คำถามจะถูกทำเครื่องหมายว่าซ้ำกับคำถามที่ถูกถามใน 6 เดือนต่อมาได้อย่างไร ดูเหมือนจะย้อนกลับไปเล็กน้อย ...
Stuart Helwig

คำตอบ:


27

หากคุณกำลังพูดถึงการลอกแท็กมันค่อนข้างตรงไปตรงมาหากคุณไม่ต้องกังวลกับสิ่งต่างๆเช่น<script>แท็ก หากสิ่งที่คุณต้องทำคือแสดงข้อความโดยไม่มีแท็กคุณสามารถทำได้ด้วยนิพจน์ทั่วไป:

<[^>]*>

หากคุณต้องกังวลเกี่ยวกับ <script>แท็กและสิ่งที่คล้ายกันคุณจะต้องมีบางสิ่งที่มีประสิทธิภาพมากกว่านิพจน์ทั่วไปเนื่องจากคุณต้องติดตามสถานะบางอย่างเช่น Context Free Grammar (CFG) แม้ว่าคุณจะสามารถทำได้ด้วยการจับคู่แบบ "ซ้ายไปขวา" หรือแบบไม่โลภ

หากคุณสามารถใช้นิพจน์ทั่วไปมีหน้าเว็บมากมายที่มีข้อมูลที่ดี:

หากคุณต้องการพฤติกรรมที่ซับซ้อนมากขึ้นของ CFG ฉันขอแนะนำให้ใช้เครื่องมือของบุคคลที่สามน่าเสียดายที่ฉันไม่รู้ว่าจะแนะนำเครื่องมือใดดี


3
นอกจากนี้คุณยังต้องกังวลเกี่ยวกับ> ในค่าแอตทริบิวต์ความคิดเห็น PI / CDATA ใน XML และความผิดปกติทั่วไปต่างๆใน HTML แบบเดิม โดยทั่วไป [X] [HT] ML ไม่สามารถตอบสนองต่อการแยกวิเคราะห์ด้วย regexps
bobince

13
นี่เป็นวิธีการที่แย่มากที่จะทำ วิธีที่ถูกต้องคือการแยกวิเคราะห์ HTML ด้วย lib และสำรวจ Dom ที่แสดงเฉพาะเนื้อหาที่อนุญาต
usr

2
@usr: ส่วนที่คุณอ้างถึงคือส่วน CFG ของคำตอบ Regex สามารถใช้สำหรับการลอกแท็กที่รวดเร็วและสกปรกมีจุดอ่อน แต่รวดเร็วและง่าย สำหรับการแยกวิเคราะห์ที่ซับซ้อนยิ่งขึ้นให้ใช้เครื่องมือที่ใช้ CFG (ในสำนวนของคุณคือ lib ที่สร้าง DOM) ฉันยังไม่ได้ทำการทดสอบ แต่ฉันขอเดิมพันว่าการแยกวิเคราะห์ DOM นั้นช้ากว่าการแยก regex ในกรณีที่ต้องพิจารณาประสิทธิภาพ
vfilby

1
@vfilby การโจมตีแรกที่เกิดขึ้นในใจคือการเขียน "<div id = \" "(ไวยากรณ์สตริง c #) สังเกตเห็นเครื่องหมายคำพูดปิดท้ายที่ขาดหายไปและไม่มีวงเล็บปีกกาปิดฉันเดาว่าสิ่งนี้จะทำให้เบราว์เซอร์สับสนและทำให้โครงสร้างแท็กไม่สมดุลได้ คุณคิดถึงการโจมตีครั้งนี้คุณแน่ใจได้หรือไม่ว่ามันไม่ได้ผลน่ารังเกียจ
usr

1
@vfilby ไม่สำคัญว่า lib ที่แยกวิเคราะห์จะสับสนหรือไม่ สิ่งที่คุณต้องทำคือรับ DOM จากมัน (DOM ใด ๆ เลย) และส่งออกเฉพาะส่วนประกอบที่อนุญาตพิเศษเท่านั้น สิ่งนี้ปลอดภัยเสมอไม่สำคัญว่า DOM ที่แยกวิเคราะห์จะเป็นอย่างไร นอกจากนี้ฉันยังบอกคุณหลายตัวอย่างที่วิธี "ง่ายๆ" ของคุณไม่สามารถลบแท็กได้
usr

100

HtmlAgilityPackฟรีและโอเพนซอร์สมีหนึ่งในตัวอย่างวิธีการที่แปลงจาก HTML เป็นข้อความธรรมดา

var plainText = HtmlUtilities.ConvertToPlainText(string html);

ป้อนสตริง HTML เช่น

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

และคุณจะได้ผลลัพธ์ข้อความธรรมดาเช่น:

hello world!

11
ฉันเคยใช้ HtmlAgilityPack มาก่อน แต่ไม่เห็นการอ้างอิงใด ๆ กับ ConvertToPlainText คุณสามารถบอกฉันได้ไหมว่าฉันจะหามันได้ที่ไหน?
horatio

8
Horatio มันรวมอยู่ในตัวอย่างหนึ่งที่มาพร้อมกับ HtmlAgilityPack: htmlagilitypack.codeplex.com/sourcecontrol/changeset/view/…
Judah Gabriel Himango

5
จริงๆแล้วไม่มีวิธีการในตัวสำหรับสิ่งนี้ใน Agility Pack สิ่งที่คุณเชื่อมโยงคือตัวอย่างที่ใช้ Agility Pack เพื่อสำรวจโครงสร้างโหนดลบscriptและstyleแท็กและเขียนข้อความภายในขององค์ประกอบอื่นลงในสตริงเอาต์พุต ฉันสงสัยว่ามันผ่านการทดสอบมากกับปัจจัยการผลิตในโลกแห่งความเป็นจริง
Lou

4
ใครช่วยให้รหัสที่ใช้งานได้แทนที่จะเป็นลิงก์ไปยังตัวอย่างที่ต้องติดตั้งใหม่เพื่อให้ทำงานได้อย่างถูกต้อง
Eric K

6
สามารถดูตัวอย่างได้ที่นี่: github.com/ceee/ReadSharp/blob/master/ReadSharp/…
StuartQ

54

ฉันไม่สามารถใช้ HtmlAgilityPack ได้ดังนั้นฉันจึงเขียนวิธีที่ดีที่สุดอันดับสองสำหรับตัวเอง

private static string HtmlToPlainText(string html)
{
    const string tagWhiteSpace = @"(>|$)(\W|\n|\r)+<";//matches one or more (white space or line breaks) between '>' and '<'
    const string stripFormatting = @"<[^>]*(>|$)";//match any character between '<' and '>', even when end tag is missing
    const string lineBreak = @"<(br|BR)\s{0,1}\/{0,1}>";//matches: <br>,<br/>,<br />,<BR>,<BR/>,<BR />
    var lineBreakRegex = new Regex(lineBreak, RegexOptions.Multiline);
    var stripFormattingRegex = new Regex(stripFormatting, RegexOptions.Multiline);
    var tagWhiteSpaceRegex = new Regex(tagWhiteSpace, RegexOptions.Multiline);

    var text = html;
    //Decode html specific characters
    text = System.Net.WebUtility.HtmlDecode(text); 
    //Remove tag whitespace/line breaks
    text = tagWhiteSpaceRegex.Replace(text, "><");
    //Replace <br /> with line breaks
    text = lineBreakRegex.Replace(text, Environment.NewLine);
    //Strip formatting
    text = stripFormattingRegex.Replace(text, string.Empty);

    return text;
}

3
& lt; บลาบลา & gt; ถูกแยกวิเคราะห์ออกดังนั้นฉันจึงย้าย text = System.Net.WebUtility.HtmlDecode (text); ไปที่ด้านล่างของวิธีการ
Luuk

1
เยี่ยมมากฉันยังได้เพิ่มคอนเดนเซอร์แบบหลายสเปซเนื่องจาก html อาจถูกสร้างขึ้นจาก CMS: var spaceRegex = new Regex ("[] {2,}", RegexOptions.None);
Enkode

บางครั้งในโค้ด html จะมีบรรทัดใหม่ของ coder (ไม่เห็นบรรทัดใหม่ในความคิดเห็นดังนั้นฉันจึงแสดงด้วย [บรรทัดใหม่] เช่น: <br> ฉัน [บรรทัดใหม่] พลาด [บรรทัดใหม่] คุณ <br > ดังนั้นมันจึงแสดงว่า: "ฉันคิดถึงคุณ" แต่มันแสดงว่าฉัน [บรรทัดใหม่] คิดถึง [บรรทัดใหม่] คุณทำให้ข้อความธรรมดาดูเจ็บปวดคุณรู้วิธีแก้ไขหรือไม่
123iamking

@ 123iamking คุณสามารถใช้สิ่งนี้ก่อนส่งคืนข้อความ : text.Replace ("[บรรทัดใหม่]", "\ n");
Eslam Badawy

ฉันใช้สิ่งนี้และตระหนักว่าบางครั้งมันออกจาก ">" ที่จุดเริ่มต้นของสตริง วิธีอื่นในการใช้ regex <[^>] *> ทำงานได้ดี
Etienne Charland

19

HTTPUtility.HTMLEncode()มีไว้เพื่อจัดการแท็ก HTML ที่เข้ารหัสเป็นสตริง ดูแลทุกการยกของหนักสำหรับคุณ จากเอกสาร MSDN :

หากมีการส่งอักขระเช่นช่องว่างและเครื่องหมายวรรคตอนในสตรีม HTTP อักขระเหล่านี้อาจตีความผิดในตอนท้ายการรับ การเข้ารหัส HTML จะแปลงอักขระที่ไม่ได้รับอนุญาตใน HTML เป็นการเทียบเท่าอักขระ - เอนทิตี การถอดรหัส HTML จะย้อนกลับการเข้ารหัส ตัวอย่างเช่นเมื่อฝังอยู่ในบล็อกข้อความอักขระ<และ>จะถูกเข้ารหัสเป็น&lt;และ&gt;สำหรับการส่ง HTTP

HTTPUtility.HTMLEncode()วิธีการมีรายละเอียดที่นี่ :

public static void HtmlEncode(
  string s,
  TextWriter output
)

การใช้งาน:

String TestString = "This is a <Test String>.";
StringWriter writer = new StringWriter();
Server.HtmlEncode(TestString, writer);
String EncodedString = writer.ToString();

คำตอบที่ดีจริงๆขอบคุณจอร์จมันยังเน้นว่าฉันถามคำถามครั้งแรกได้ไม่ดีแค่ไหน ขออภัย.
Stuart Helwig

html agility pack ล้าสมัยและไม่รองรับ html5
abzarak

9

หากต้องการเพิ่มคำตอบของ vfilby คุณสามารถทำการแทนที่ RegEx ภายในรหัสของคุณ ไม่จำเป็นต้องเรียนใหม่ ในกรณีที่มือใหม่คนอื่น ๆ เช่นตัวเองสะดุดกับคำถามนี้

using System.Text.RegularExpressions;

จากนั้น ...

private string StripHtml(string source)
{
        string output;

        //get rid of HTML tags
        output = Regex.Replace(source, "<[^>]*>", string.Empty);

        //get rid of multiple blank lines
        output = Regex.Replace(output, @"^\s*$\n", string.Empty, RegexOptions.Multiline);

        return output;
}

19
ไม่ดี! สิ่งนี้สามารถหลอกให้มีสคริปต์ได้โดยการละเว้นวงเล็บมุมปิด พวกไม่เคยทำบัญชีดำ คุณไม่สามารถล้างข้อมูลที่ป้อนโดยการขึ้นบัญชีดำ นี่มันผิดมาก
usr

7

กระบวนการสามขั้นตอนสำหรับการแปลง HTML เป็นข้อความธรรมดา

ก่อนอื่นคุณต้องติดตั้ง Nuget Package สำหรับHtmlAgilityPack Second สร้างคลาสนี้

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

โดยใช้ชั้นเรียนข้างต้นโดยอ้างอิงคำตอบของ Judah Himango

ประการที่สามคุณต้องสร้าง Object ของคลาสข้างต้นและใช้ConvertHtml(HTMLContent)Method สำหรับการแปลง HTML เป็น Plain Text แทนConvertToPlainText(string html);

HtmlToText htt=new HtmlToText();
var plainText = htt.ConvertHtml(HTMLContent);

ฉันสามารถข้ามการแปลงลิงค์ใน html ได้ไหม ฉันต้องเก็บลิงค์ใน html เมื่อแปลงเป็นข้อความ?
coder771

5

มีข้อ จำกัด ที่จะไม่ยุบช่องว่างแบบอินไลน์ยาว ๆ แต่เป็นแบบพกพาได้อย่างแน่นอนและเคารพรูปแบบเช่นเว็บเบราว์เซอร์

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

3

ฉันคิดว่าวิธีที่ง่ายที่สุดคือการสร้างวิธีการขยาย 'สตริง' (ตามสิ่งที่ผู้ใช้ Richard แนะนำ):

using System;
using System.Text.RegularExpressions;

public static class StringHelpers
{
    public static string StripHTML(this string HTMLText)
        {
            var reg = new Regex("<[^>]+>", RegexOptions.IgnoreCase);
            return reg.Replace(HTMLText, "");
        }
}

จากนั้นใช้วิธีการขยายนี้กับตัวแปร 'string' ในโปรแกรมของคุณ:

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

ฉันใช้วิธีส่วนขยายนี้เพื่อแปลงความคิดเห็นที่จัดรูปแบบ html เป็นข้อความธรรมดาดังนั้นมันจะแสดงอย่างถูกต้องในรายงานคริสตัลและทำงานได้อย่างสมบูรณ์แบบ!


2

ไม่มีเมธอดที่มีชื่อ 'ConvertToPlainText' ใน HtmlAgilityPack แต่คุณสามารถแปลงสตริง html เป็นสตริง CLEAR ด้วย:

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

นั่นได้ผลสำหรับฉัน แต่ฉันไม่พบวิธีการที่มีชื่อ 'ConvertToPlainText' ใน 'HtmlAgilityPack'


2

วิธีที่ง่ายที่สุดที่ฉันพบ:

HtmlFilter.ConvertToPlainText(html);

คลาส HtmlFilter อยู่ใน Microsoft.TeamFoundation.WorkItemTracking.Controls.dll

dll สามารถพบได้ในโฟลเดอร์ดังนี้:% ProgramFiles% \ Common Files \ microsoft shared \ Team Foundation Server \ 14.0 \

ใน VS 2015 dll ยังต้องการการอ้างอิงถึง Microsoft.TeamFoundation.WorkItemTracking.Common.dll ซึ่งอยู่ในโฟลเดอร์เดียวกัน


มันดูแลแท็กสคริปต์และจัดรูปแบบเป็นตัวเอียงตัวหนา ฯลฯ หรือไม่
Samra

2
ขอแนะนำการพึ่งพาฐานรากของทีมสำหรับการแปลง html เป็นข้อความธรรมดาน่าสงสัยมาก ...
ViRuSTriNiTy

1

หากคุณมีข้อมูลที่มีแท็ก HTML และต้องการแสดงข้อมูลเพื่อให้บุคคลอื่นสามารถดูแท็กได้ให้ใช้ HttpServerUtility :: HtmlEncode

หากคุณมีข้อมูลที่มีแท็ก HTML อยู่และต้องการให้ผู้ใช้เห็นแท็กที่แสดงผลให้แสดงข้อความตามที่เป็นอยู่ หากข้อความแสดงถึงหน้าเว็บทั้งหมดให้ใช้ IFRAME สำหรับหน้านั้น

หากคุณมีข้อมูลที่มีแท็ก HTML และต้องการตัดแท็กออกและเพียงแค่แสดงข้อความที่ไม่ได้จัดรูปแบบให้ใช้นิพจน์ทั่วไป


ใน php มีฟังก์ชันที่เรียกว่า striptags () บางทีคุณอาจมีบางอย่างที่คล้ายกัน
markus

"ใช้นิพจน์ทั่วไป" ไม่! นี่จะเป็นการขึ้นบัญชีดำ คุณสามารถทำรายการที่อนุญาตพิเศษได้อย่างปลอดภัยเท่านั้น ตัวอย่างเช่นคุณเคยจำได้ไหมว่า style attibute สามารถมี "background: url ('javascript: ... ');"? ไม่แน่นอนฉันก็ไม่มีเช่นกัน นั่นคือสาเหตุที่การขึ้นบัญชีดำไม่ทำงาน
usr

1

ฉันประสบปัญหาที่คล้ายกันและพบทางออกที่ดีที่สุด โค้ดด้านล่างทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

}

อักขระ Escape เช่น \ n และ \ r ต้องถูกลบออกก่อนเนื่องจากทำให้ regexes หยุดทำงานตามที่คาดไว้

ยิ่งไปกว่านั้นเพื่อให้สตริงผลลัพธ์แสดงอย่างถูกต้องในกล่องข้อความเราอาจต้องแยกมันและตั้งค่าคุณสมบัติเส้นของกล่องข้อความแทนการกำหนดให้กับคุณสมบัติข้อความ

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

ที่มา: https://www.codeproject.com/Articles/11902/Convert-HTML-to-Plain-Text-2


0

ขึ้นอยู่กับความหมายของ "html" กรณีที่ซับซ้อนที่สุดคือหน้าเว็บที่สมบูรณ์ นั่นเป็นวิธีที่ง่ายที่สุดในการจัดการเนื่องจากคุณสามารถใช้เว็บเบราว์เซอร์ในโหมดข้อความได้ ดูบทความ Wikipedia ที่แสดงรายการเว็บเบราว์เซอร์รวมถึงเบราว์เซอร์โหมดข้อความ Lynx น่าจะเป็นที่รู้จักกันดีที่สุด แต่อย่างใดอย่างหนึ่งอาจดีกว่าสำหรับความต้องการของคุณ


ตามที่เขาพูดว่า "ฉันมีตัวอย่าง Html เก็บไว้ในตาราง"
M ที่

0

นี่คือทางออกของฉัน:

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

ตัวอย่าง:

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

0

ฉันมีคำถามเดียวกันเพียงแค่ html ของฉันมีเค้าโครงที่รู้จักกันล่วงหน้าง่ายๆเช่น:

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

ดังนั้นฉันจึงใช้รหัสง่ายๆดังกล่าว:

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

ผลลัพธ์ใด:

abc
def

0

ไม่ได้เขียน แต่ใช้:

using HtmlAgilityPack;
using System;
using System.IO;
using System.Text.RegularExpressions;

namespace foo {
  //small but important modification to class https://github.com/zzzprojects/html-agility-pack/blob/master/src/Samples/Html2Txt/HtmlConvert.cs
  public static class HtmlToText {

    public static string Convert(string path) {
      HtmlDocument doc = new HtmlDocument();
      doc.Load(path);
      return ConvertDoc(doc);
    }

    public static string ConvertHtml(string html) {
      HtmlDocument doc = new HtmlDocument();
      doc.LoadHtml(html);
      return ConvertDoc(doc);
    }

    public static string ConvertDoc(HtmlDocument doc) {
      using (StringWriter sw = new StringWriter()) {
        ConvertTo(doc.DocumentNode, sw);
        sw.Flush();
        return sw.ToString();
      }
    }

    internal static void ConvertContentTo(HtmlNode node, TextWriter outText, PreceedingDomTextInfo textInfo) {
      foreach (HtmlNode subnode in node.ChildNodes) {
        ConvertTo(subnode, outText, textInfo);
      }
    }
    public static void ConvertTo(HtmlNode node, TextWriter outText) {
      ConvertTo(node, outText, new PreceedingDomTextInfo(false));
    }
    internal static void ConvertTo(HtmlNode node, TextWriter outText, PreceedingDomTextInfo textInfo) {
      string html;
      switch (node.NodeType) {
        case HtmlNodeType.Comment:
          // don't output comments
          break;
        case HtmlNodeType.Document:
          ConvertContentTo(node, outText, textInfo);
          break;
        case HtmlNodeType.Text:
          // script and style must not be output
          string parentName = node.ParentNode.Name;
          if ((parentName == "script") || (parentName == "style")) {
            break;
          }
          // get text
          html = ((HtmlTextNode)node).Text;
          // is it in fact a special closing node output as text?
          if (HtmlNode.IsOverlappedClosingElement(html)) {
            break;
          }
          // check the text is meaningful and not a bunch of whitespaces
          if (html.Length == 0) {
            break;
          }
          if (!textInfo.WritePrecedingWhiteSpace || textInfo.LastCharWasSpace) {
            html = html.TrimStart();
            if (html.Length == 0) { break; }
            textInfo.IsFirstTextOfDocWritten.Value = textInfo.WritePrecedingWhiteSpace = true;
          }
          outText.Write(HtmlEntity.DeEntitize(Regex.Replace(html.TrimEnd(), @"\s{2,}", " ")));
          if (textInfo.LastCharWasSpace = char.IsWhiteSpace(html[html.Length - 1])) {
            outText.Write(' ');
          }
          break;
        case HtmlNodeType.Element:
          string endElementString = null;
          bool isInline;
          bool skip = false;
          int listIndex = 0;
          switch (node.Name) {
            case "nav":
              skip = true;
              isInline = false;
              break;
            case "body":
            case "section":
            case "article":
            case "aside":
            case "h1":
            case "h2":
            case "header":
            case "footer":
            case "address":
            case "main":
            case "div":
            case "p": // stylistic - adjust as you tend to use
              if (textInfo.IsFirstTextOfDocWritten) {
                outText.Write("\r\n");
              }
              endElementString = "\r\n";
              isInline = false;
              break;
            case "br":
              outText.Write("\r\n");
              skip = true;
              textInfo.WritePrecedingWhiteSpace = false;
              isInline = true;
              break;
            case "a":
              if (node.Attributes.Contains("href")) {
                string href = node.Attributes["href"].Value.Trim();
                if (node.InnerText.IndexOf(href, StringComparison.InvariantCultureIgnoreCase) == -1) {
                  endElementString = "<" + href + ">";
                }
              }
              isInline = true;
              break;
            case "li":
              if (textInfo.ListIndex > 0) {
                outText.Write("\r\n{0}.\t", textInfo.ListIndex++);
              } else {
                outText.Write("\r\n*\t"); //using '*' as bullet char, with tab after, but whatever you want eg "\t->", if utf-8 0x2022
              }
              isInline = false;
              break;
            case "ol":
              listIndex = 1;
              goto case "ul";
            case "ul": //not handling nested lists any differently at this stage - that is getting close to rendering problems
              endElementString = "\r\n";
              isInline = false;
              break;
            case "img": //inline-block in reality
              if (node.Attributes.Contains("alt")) {
                outText.Write('[' + node.Attributes["alt"].Value);
                endElementString = "]";
              }
              if (node.Attributes.Contains("src")) {
                outText.Write('<' + node.Attributes["src"].Value + '>');
              }
              isInline = true;
              break;
            default:
              isInline = true;
              break;
          }
          if (!skip && node.HasChildNodes) {
            ConvertContentTo(node, outText, isInline ? textInfo : new PreceedingDomTextInfo(textInfo.IsFirstTextOfDocWritten) { ListIndex = listIndex });
          }
          if (endElementString != null) {
            outText.Write(endElementString);
          }
          break;
      }
    }
  }
  internal class PreceedingDomTextInfo {
    public PreceedingDomTextInfo(BoolWrapper isFirstTextOfDocWritten) {
      IsFirstTextOfDocWritten = isFirstTextOfDocWritten;
    }
    public bool WritePrecedingWhiteSpace { get; set; }
    public bool LastCharWasSpace { get; set; }
    public readonly BoolWrapper IsFirstTextOfDocWritten;
    public int ListIndex { get; set; }
  }
  internal class BoolWrapper {
    public BoolWrapper() { }
    public bool Value { get; set; }
    public static implicit operator bool(BoolWrapper boolWrapper) {
      return boolWrapper.Value;
    }
    public static implicit operator BoolWrapper(bool boolWrapper) {
      return new BoolWrapper { Value = boolWrapper };
    }
  }
}


0

สำหรับใครก็ตามที่กำลังมองหาวิธีแก้ปัญหาที่แน่นอนสำหรับคำถาม OP สำหรับตัวย่อแบบข้อความของเอกสาร html ที่กำหนดโดยไม่ต้องขึ้นบรรทัดใหม่และแท็ก HTML โปรดค้นหาวิธีแก้ไขด้านล่าง

เช่นเดียวกับทุกโซลูชันที่เสนอมีข้อสันนิษฐานบางประการเกี่ยวกับรหัสด้านล่าง:

  • แท็กสคริปต์หรือสไตล์ไม่ควรมีแท็กสคริปต์และสไตล์เป็นส่วนหนึ่งของสคริปต์
  • เพียงองค์ประกอบแบบอินไลน์ที่สำคัญจะ inlined ไม่ต้องเว้นวรรคเช่นควรเอาท์พุทhe<span>ll</span>o helloรายการแท็กแบบอินไลน์: https://www.w3schools.com/htmL/html_blocks.asp

เมื่อพิจารณาจากข้างต้นส่วนขยายสตริงต่อไปนี้ที่มีนิพจน์ทั่วไปที่คอมไพล์แล้วจะแสดงผลข้อความธรรมดาที่คาดหวังโดยคำนึงถึงอักขระที่ใช้ Escape html และ null ในอินพุต null

public static class StringExtensions
{
    public static string ConvertToPlain(this string html)
    {
        if (html == null)
        {
            return html;
        }

        html = scriptRegex.Replace(html, string.Empty);
        html = inlineTagRegex.Replace(html, string.Empty);
        html = tagRegex.Replace(html, " ");
        html = HttpUtility.HtmlDecode(html);
        html = multiWhitespaceRegex.Replace(html, " ");

        return html.Trim();
    }

    private static readonly Regex inlineTagRegex = new Regex("<\\/?(a|span|sub|sup|b|i|strong|small|big|em|label|q)[^>]*>", RegexOptions.Compiled | RegexOptions.Singleline);
    private static readonly Regex scriptRegex = new Regex("<(script|style)[^>]*?>.*?</\\1>", RegexOptions.Compiled | RegexOptions.Singleline);
    private static readonly Regex tagRegex = new Regex("<[^>]+>", RegexOptions.Compiled | RegexOptions.Singleline);
    private static readonly Regex multiWhitespaceRegex = new Regex("\\s+", RegexOptions.Compiled | RegexOptions.Singleline);
}

-4

สตริงคงที่สาธารณะ StripTags2 (สตริง html) {return html.Replace ("<", "<"). Replace (">", ">"); }

ด้วยวิธีนี้คุณจะหลีกเลี่ยง "<" และ ">" ทั้งหมดในสตริง นี่คือสิ่งที่คุณต้องการหรือไม่?


...อา. ตอนนี้คำตอบ (พร้อมกับการตีความคำถามที่คลุมเครือ) เปลี่ยนไปอย่างสิ้นเชิงฉันจะเลือก nits ที่ไม่มี & amp; การเข้ารหัสแทน ;-)
bobince

2
ฉันไม่คิดว่าเป็นความคิดที่ดีที่จะสร้างล้อใหม่โดยเฉพาะอย่างยิ่งเมื่อล้อของคุณเป็นสี่เหลี่ยม คุณควรใช้ HTMLEncode แทน
Kramii
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.