ASP.NET의 문자열에서 HTML 태그를 제거하려면 어떻게해야합니까?


123

ASP.NET을 사용하여 어떻게 주어진 문자열에서 HTML 태그를 안정적으로 제거 할 수 있습니까 (예 : 정규식을 사용하지 않음)? PHP와 같은 것을 찾고 strip_tags있습니다.

예:

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

산출:

"여보세요"

나는 바퀴를 재발 명하지 않으려 고 노력하고 있지만 지금까지 내 요구를 충족시키는 것을 찾지 못했습니다.


PHP strip_tags가 뒤에서 정규식을 사용한다고 상상할 수 있습니다!
stevehipwell 2009

10
@Daniel : 특히 중첩이있는 경우 정규식이 매우 나쁘기 때문입니다.
Joel Coehoorn

흠, PHP의 Strip_Tags는 공식적인 메모와 주석에서 특히 신뢰할 수있는 것처럼 보이지 않습니다. uk.php.net/strip_tags
Zhaph-Ben Duguid

답변:


112

문자열에서 모든 HTML 태그를 제거 하는 경우 정규식에서도 안정적 으로 작동 합니다. 바꾸다:

<[^>]*(>|$)

전역 적으로 빈 문자열로. 나중에 문자열을 정규화하는 것을 잊지 마십시오.

[\s\r\n]+

단일 공간으로 결과를 트리밍합니다. 선택적으로 HTML 문자 엔티티를 실제 문자로 다시 바꿉니다.

참고 :

  1. 제한이 있습니다. HTML 및 XML >은 속성 값을 허용 합니다. 이 솔루션 이러한 값이 발생하면 깨진 마크 업 반환합니다.
  2. 솔루션은 다음과 같이 기술적으로 안전합니다. 결과에는 사이트 간 스크립팅을 수행하거나 페이지 레이아웃을 깨는 데 사용할 수있는 내용이 포함되지 않습니다. 그것은 매우 깨끗하지 않습니다.
  3. 모든 HTML 및 정규식과 마찬가지로 : 모든 상황에서 올바르게 사용해야하는 경우 적절한 구문 분석기를
    사용하십시오 .

52
요청되지는 않았지만 많은 독자들이 .NET과 같은 HTM 인코딩을 제거하고 싶어 할 것이라고 생각합니다 &quote;. 나는 그것을 위해 그것을 결합합니다 WebUtility.HtmlDecode(다시 태그를 제거하지 않을 것입니다). 그것은 다시 수 있기 때문에, 태그 제거 후 사용 &gt;하고 &lt;. 예WebUtility.HtmlDecode(Regex.Replace(myTextVariable, "<[^>]*(>|$)", string.Empty))
야후 심각한

@YahooSerious 예를 들어 주셔서 감사합니다. 이것은 훌륭하게 작동합니다. 감사합니다.
SearchForKnowledge apr

Html Agility Pack은 갈 길입니다. 웹 양식에서 다시 사용하여 콘텐츠를 사용하기 위해 전체 웹 페이지를 제거했습니다!
Bojangles

3
@YahooSerious 이것은 XSS 벡터를 허용하지만 & gt; 스크립트 & lt; alert ( "XXS"); & gt; / 스크립트 & lt; 정규식에 의해 삭제되지 않지만 HtmlDecode에 의해 <script> alert ( "XXS"); </ script>로 변환됩니다.

1
@Heather 아주 좋은 지적입니다. HTML 태그 제거는 엔터티 디코딩 후에 다시 수행해야합니다.
Tomalak

76

지금 HTMLAgilityPack을 다운로드하십시오! ;) 링크 다운로드

이를 통해 HTML을로드하고 구문 분석 할 수 있습니다. 그런 다음 DOM을 탐색하고 모든 속성의 내부 값을 추출 할 수 있습니다. 진지하게, 최대 10 줄의 코드가 필요합니다. 가장 훌륭한 무료 .net 라이브러리 중 하나입니다.

다음은 샘플입니다.

            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

또는 단순히 doc.DocumentNode.InnerText를 사용하십시오. 이것은 공백 처리에 약간의 문제가 있지만…
jessehouwing

17
if (doc == null)수표입니까? 이것은 항상 거짓이지, 그렇지 않습니까?
avesse

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

간단하고 멋지다. 감사!
Tillito

5
많은 문제가 있음-<또는>가있는 속성을 처리하지 않고 .NET을 실행하지 않는 한 두 줄 이상의 태그를 잘 처리하지 않습니다 RegexOptions.SingleLine.
ChrisF

2
아니요, "<[^>] *>"를 사용합니다.
Paul Kienitz

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
비 유닉스 줄 바꿈을 포함하여 많은 경우에서 작동하지 않습니다.
ChrisF

6

나는 이것을 asp.net 포럼에 게시했지만 여전히 가장 쉬운 솔루션 중 하나 인 것 같습니다. 가장 빠르거나 가장 효율적이라고 보장하지는 않지만 꽤 신뢰할 수 있습니다. .NET에서는 HTML 웹 컨트롤 개체 자체를 사용할 수 있습니다. 정말 필요한 것은 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 2011 년

이러지마 이 솔루션은 인코딩되지 않은 html을 출력에 직접 삽입합니다. 이로 인해 크로스 사이트 스크립팅 공격에 노출 될 수 있습니다. html 문자열을 변경할 수있는 모든 사람이 임의의 html 및 javascript를 응용 프로그램에 삽입하도록 허용했습니다!
saille

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

3
string result = Regex.Replace(anytext, @"<(.|\n)*?>", string.Empty);

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

여기에 제안 된 Regex 기반 솔루션을 살펴 보았지만 가장 사소한 경우를 제외하고는 확신을주지 않습니다. 속성의 꺾쇠 괄호 만 있으면 깨질 수 있습니다. 잘못된 형식의 HTML은 말할 것도 없습니다. 그리고 같은 엔티티는 어떻습니까?&amp; 어떻습니까? HTML을 일반 텍스트로 변환하려면 엔터티도 디코딩해야합니다.

그래서 아래 방법을 제안합니다.

HtmlAgilityPack을 사용하는 이 확장 메서드는 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

두 번째 매개 변수, 즉 일부 태그를 유지하려면 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.