ASP.NETで文字列からHTMLタグを削除するにはどうすればよいですか?


123

ASP.NETを使用して、指定された文字列からHTMLタグを確実に削除するにはどうすればよいですか(つまり、正規表現を使用しません)。PHPのようなものを探していstrip_tagsます。

例:

<ul><li>Hello</li></ul>

出力:

"こんにちは"

私は車輪を再発明しないように努めていますが、今のところ自分のニーズを満たすものを見つけていません。


PHPのstrip_tagsが舞台裏で正規表現を使用していると思います!
stevehipwell 2009

10
@Daniel:特にネストがある場合、正規表現は非常に悪いためです。
Joel Coehoorn、2009

うーん、PHPのStrip_Tagsは公式ノートとコメントのどちらかで特に信頼できるようには見えません:uk.php.net/strip_tags
Zhaph-Ben Duguid 2009年

回答:


112

文字列からすべての HTMLタグを削除するだけの場合、これは正規表現でも確実に機能します。交換:

<[^>]*(>|$)

空の文字列で、グローバルに。後で文字列を正規化することを忘れないでください:

[\s\r\n]+

単一のスペースで、結果をトリミングします。オプションで、HTML文字エンティティを実際の文字に置き換えます。

  1. 制限があります。HTMLとXML >では属性値を使用できます。このソリューション、そのような値に遭遇すると壊れたマークアップ返します。
  2. ソリューションは、次のように技術的に安全です。結果には、クロスサイトスクリプティングの実行やページレイアウトの破壊に使用できるものは含まれません。あまりきれいではありません。
  3. すべてのものと同様にHTMLと正規表現:すべての状況で正しく取得する必要がある場合は、適切なパーサーを
    使用してください。

52
要求されていませんが、多くの読者はのようにHTMエンコーディングも削除したいと思うでしょう&quote;。私はそれをWebUtility.HtmlDecodeそのために組み合わせます(これはタグを削除しません)。それは書き換え可能性があるため、タグを除去した後、それを使用&gt;して&lt;。例えばWebUtility.HtmlDecode(Regex.Replace(myTextVariable, "<[^>]*(>|$)", string.Empty))
ヤフーシリアス

@YahooSerious例を提供していただきありがとうございます。これはうまくいきます。ありがとうございました。
SearchForKnowledge 2015

Html Agility Packを使用する方法です。コンテンツを使用するために、Webフォーム全体でWebページ全体を削除するために使用しました。
Bojangles 2015年

3
@YahooSeriousこれによりXSSベクトルが許可されます&gt; スクリプト&lt; alert( "XXS"); &gt; /スクリプト&lt; 正規表現ではサニタイズされませんが、HtmlDecodeで<script> alert( "XXS"); </ script>に変換されます

1
@ヘザー非常に良い点。HTMLタグの除去は、エンティティのデコード後に再度実行する必要があります。
Tomalak

76

今すぐHTMLAgilityPackをダウンロードしてください!;) リンクをダウンロード

これにより、HTMLを読み込んで解析できます。次に、DOMをナビゲートして、すべての属性の内部値を抽出できます。真剣に、それはあなたに最大で約10行のコードを必要とします。これは、世の中で最も優れた無料の.netライブラリの1つです。

ここにサンプルがあります:

            string htmlContents = new System.IO.StreamReader(resultsStream,Encoding.UTF8,true).ReadToEnd();

            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(htmlContents);
            if (doc == null) return null;

            string output = "";
            foreach (var node in doc.DocumentNode.ChildNodes)
            {
                output += node.InnerText;
            }

2
すべてのtext()ノードにクエリを実行して、コンテンツと文字列をトリミングすることもできます。スペースで結合します。IEnumerable<string> allText = doc.DocumentNode.SelectNodes("//text()").Select(n => n.InnerText.Trim())
jessehouwing 2012年

または、単にdoc.DocumentNode.InnerTextを使用しますが、これはホワイトスペースの処理に問題があるようです...
jessehouwing

17
なぜif (doc == null)チェックですか?これは常に誤りです、そうではありませんか?
avesse 2012年

67
Regex.Replace(htmlText, "<.*?>", string.Empty);

シンプルでいい。ありがとう!
Tillito 2012年

5
多くの問題があります-<または>が含まれる属性を処理せず、で実行しない限り、複数行にまたがるタグをうまく処理できませんRegexOptions.SingleLine
ChrisF 2013年

2
いいえ、 "<[^>] *>"を使用してください。
Paul Kienitz、2018年

11
protected string StripHtml(string Txt)
{
    return Regex.Replace(Txt, "<(.|\\n)*?>", string.Empty);
}    

Protected Function StripHtml(Txt as String) as String
    Return Regex.Replace(Txt, "<(.|\n)*?>", String.Empty)
End Function

2
UNIX以外の改行を含む多くのケースでは機能しません。
ChrisF 2013年

6

私はこれをasp.netフォーラムに投稿しましたが、それでもまだ最も簡単な解決策の1つであるようです。私はそれが最速または最も効率的であることを保証しませんが、それはかなり信頼できます。.NETでは、HTML Webコントロールオブジェクト自体を使用できます。本当に必要なことは、DIVなどの一時的なHTMLオブジェクトに文字列を挿入し、組み込みの「InnerText」を使用して、タグに含まれていないすべてのテキストを取得することです。簡単なC#の例については、以下を参照してください。


System.Web.UI.HtmlControls.HtmlGenericControl htmlDiv = new System.Web.UI.HtmlControls.HtmlGenericControl("div");
htmlDiv.InnerHtml = htmlString;
String plainText = htmlDiv.InnerText;

これは機能していないようです。簡単なInnerHtml = "<b> foo </ b>"でテストしました。およびInnerTextの値は "<b> foo </ b>" :(
Axarydax

これを行わないでください。このソリューションは、エンコードされていないhtmlを直接出力に挿入します。これにより、クロスサイトスクリプティング攻撃の可能性が広がります。HTML文字列を変更できる任意のユーザーに、任意のHTMLおよびJavaScriptをアプリケーションに挿入することを許可しただけです。
2015年

5

私はc#で非常に高速なメソッドを作成しました。これは、CodeProject に関する記事でホストされています

その利点は、より優れたパフォーマンスという名前と番号HTMLエンティティ(のようなものを交換する能力の中で、ある&amp;amp;&203;)とコメントブロックの交換を、より。

CodeProject関連記事をお読みください。

ありがとうございました。


4

HtmlAgilityPackを使用できない人のために、.NETs XMLリーダーはオプションです。これは適切にフォーマットされたHTMLでは失敗する可能性がありますが、常にregxを使用してキャッチをバックアップとして追加してください。これは高速ではありませんが、古い学校のデバッグのステップに良い機会を提供することに注意してください。

public static string RemoveHTMLTags(string content)
    {
        var cleaned = string.Empty;
        try
        {
            StringBuilder textOnly = new StringBuilder();
            using (var reader = XmlNodeReader.Create(new System.IO.StringReader("<xml>" + content + "</xml>")))
            {
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Text)
                        textOnly.Append(reader.ReadContentAsString());
                }
            }
            cleaned = textOnly.ToString();
        }
        catch
        {
            //A tag is probably not closed. fallback to regex string clean.
            string textOnly = string.Empty;
            Regex tagRemove = new Regex(@"<[^>]*(>|$)");
            Regex compressSpaces = new Regex(@"[\s\r\n]+");
            textOnly = tagRemove.Replace(content, string.Empty);
            textOnly = compressSpaces.Replace(textOnly, " ");
            cleaned = textOnly;
        }

        return cleaned;
    }


1

Michael Tiptopのソリューションが機能しないことについて意見を交換している人のために、これを行う.Net4 +の方法を次に示します。

public static string StripTags(this string markup)
{
    try
    {
        StringReader sr = new StringReader(markup);
        XPathDocument doc;
        using (XmlReader xr = XmlReader.Create(sr,
                           new XmlReaderSettings()
                           {
                               ConformanceLevel = ConformanceLevel.Fragment
                               // for multiple roots
                           }))
        {
            doc = new XPathDocument(xr);
        }

        return doc.CreateNavigator().Value; // .Value is similar to .InnerText of  
                                           //  XmlDocument or JavaScript's innerText
    }
    catch
    {
        return string.Empty;
    }
}

1
using System.Text.RegularExpressions;

string str = Regex.Replace(HttpUtility.HtmlDecode(HTMLString), "<.*?>", string.Empty);

0

私はここで提案された正規表現ベースのソリューションを見てきましたが、それらは非常に些細な場合を除いて、私に自信を与えません。属性の山括弧は、壊れるのに必要なすべてのことであり、野生の不正なHTMLは言うまでもありません。そして、エンティティのようなものはどう&amp;ですか?HTMLをプレーンテキストに変換する場合は、エンティティもデコードする必要があります。

そこで、以下の方法を提案します。

HtmlAgilityPackを使用して、この拡張メソッドはHTMLフラグメントからすべてのHTMLタグを効率的に取り除きます。のようなHTMLエンティティもデコードします&amp;。内側のテキストアイテムのみを返し、各テキストアイテムの間に改行を入れます。

public static string RemoveHtmlTags(this string html)
{
        if (String.IsNullOrEmpty(html))
            return html;

        var doc = new HtmlAgilityPack.HtmlDocument();
        doc.LoadHtml(html);

        if (doc.DocumentNode == null || doc.DocumentNode.ChildNodes == null)
        {
            return WebUtility.HtmlDecode(html);
        }

        var sb = new StringBuilder();

        var i = 0;

        foreach (var node in doc.DocumentNode.ChildNodes)
        {
            var text = node.InnerText.SafeTrim();

            if (!String.IsNullOrEmpty(text))
            {
                sb.Append(text);

                if (i < doc.DocumentNode.ChildNodes.Count - 1)
                {
                    sb.Append(Environment.NewLine);
                }
            }

            i++;
        }

        var result = sb.ToString();

        return WebUtility.HtmlDecode(result);
}

public static string SafeTrim(this string str)
{
    if (str == null)
        return null;

    return str.Trim();
}

あなたは本当に深刻であれば、あなたも(特定のHTMLタグの内容を無視したいと思い<script><style><svg><head><object>彼らはおそらく、我々は後にしている感覚で読めるコンテンツが含まれていないので、気になります!)。何をするかは、状況や行きたいところによって異なりますが、HtmlAgilityPackを使用すると、選択したタグをホワイトリストまたはブラックリストに登録することはかなり簡単になります。

コンテンツをHTMLページにレンダリングする場合は、XSSの脆弱性とその防止方法を必ず理解してください。つまり、HTMLページにレンダリングされるユーザー入力テキストを常にエンコードします(に>なる&gt;など)。


0

2番目のパラメーター、つまりいくつかのタグを保持するには、HTMLagilityPackを使用して次のようなコードが必要になる場合があります。

public string StripTags(HtmlNode documentNode, IList keepTags)
{
    var result = new StringBuilder();
        foreach (var childNode in documentNode.ChildNodes)
        {
            if (childNode.Name.ToLower() == "#text")
            {
                result.Append(childNode.InnerText);
            }
            else
            {
                if (!keepTags.Contains(childNode.Name.ToLower()))
                {
                    result.Append(StripTags(childNode, keepTags));
                }
                else
                {
                    result.Append(childNode.OuterHtml.Replace(childNode.InnerHtml, StripTags(childNode, keepTags)));
                }
            }
        }
        return result.ToString();
    }

このページの詳細:http : //nalgorithm.com/2015/11/20/strip-html-tags-of-an-html-in-c-strip_html-php-equivalent/


0

HtmlAgilityPackの代替であるAngleSharpを使用してこれを行うこともできます(そのHAPが悪いわけではありません)。HTMLソースからテキストを取り出すには、HAPよりも使いやすいです。

var parser = new HtmlParser();
var htmlDocument = parser.ParseDocument(source);
var text = htmlDocument.Body.Text();

あなたはを見てとることができ、キー特徴 HAPよりも「より良い」という時に、彼らはケースを作るのセクションを。ほとんどの場合、それはおそらく現在の質問には行き過ぎですが、それでも興味深い代替手段です。


-4

単に使う string.StripHTML();


3
@Serpitonが指摘しているように、BCLにはそのようなメソッドはありません。このメソッドの実装を指すか、独自のメソッドを提供できますか?
Sven Grosen、2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.