문제

그래서 방금 내 사이트가 오늘 서버를 시작 했고이 기능이 범인이라고 생각합니다. 누구든지 문제가 무엇인지 말해 줄 수 있습니까? 나는 그것을 알아낼 수없는 것 같다 :

Public Function CleanText(ByVal str As String) As String    
'removes HTML tags and other characters that title tags and descriptions don't like
    If Not String.IsNullOrEmpty(str) Then
        'mini db of extended tags to get rid of
        Dim indexChars() As String = {"<a", "<img", "<input type=""hidden"" name=""tax""", "<input type=""hidden"" name=""handling""", "<span", "<p", "<ul", "<div", "<embed", "<object", "<param"}

        For i As Integer = 0 To indexChars.GetUpperBound(0) 'loop through indexchars array
            Dim indexOfInput As Integer = 0
            Do 'get rid of links
                indexOfInput = str.IndexOf(indexChars(i)) 'find instance of indexChar
                If indexOfInput <> -1 Then
                    Dim indexNextLeftBracket As Integer = str.IndexOf("<", indexOfInput) + 1
                    Dim indexRightBracket As Integer = str.IndexOf(">", indexOfInput) + 1
                    'check to make sure a right bracket hasn't been left off a tag
                    If indexNextLeftBracket > indexRightBracket Then 'normal case
                        str = str.Remove(indexOfInput, indexRightBracket - indexOfInput)
                    Else
                        'add the right bracket right before the next left bracket, just remove everything
                        'in the bad tag
                        str = str.Insert(indexNextLeftBracket - 1, ">")
                        indexRightBracket = str.IndexOf(">", indexOfInput) + 1
                        str = str.Remove(indexOfInput, indexRightBracket - indexOfInput)
                    End If
                End If
            Loop Until indexOfInput = -1
        Next
    End If
    Return str
End Function
도움이 되었습니까?

해결책

이와 같은 것이 더 간단하지 않습니까? (좋아요, 게시 된 코드와 동일하지 않다는 것을 알고 있습니다) :

public string StripHTMLTags(string text)
{
    return Regex.Replace(text, @"<(.|\n)*?>", string.Empty);
}

(vb.net으로의 전환은 사소해야합니다!)

참고 : 자주 실행하는 경우 두 가지 성능 향상이 있습니다. Regex.

하나는 사전 컴파일 된 표현식을 사용하여 약간의 재 작성이 필요합니다.

두 번째는 정규 표현의 비과축 형태를 사용하는 것입니다. .NET 일반 표현식은 (? :) 구문을 구현하여 구문을 구현하여, 캡처 된 텍스트의 성능 페널티를 뒤로 회의로 기억하지 않고 그룹화를 수행 할 수 있습니다. 이 구문을 사용하면 위의 정규 표현식이 다음으로 변경 될 수 있습니다.

@"<(?:.|\n)*?>"

다른 팁

이 라인도 잘못되었습니다.

Dim indexNextLeftBracket As Integer = str.IndexOf("<", indexOfInput) + 1

이 시점에서 indexofinput에 의해 언급 된 위치의 문자는 이미 '<' '이기 때문에 항상 indexnlextleftbracket을 indexxtleftbracket을 Indexxtleftbracket을 설정하는 것이 보장됩니다. 대신 이것을하십시오 :

Dim indexNextLeftBracket As Integer = str.IndexOf("<", indexOfInput+1) + 1

또한 IF 문에 조항을 추가하여 문자열이 해당 표현에 충분히 길어 지는지 확인하십시오.

마지막으로, 다른 사람들이 말했듯 이이 코드는이 코드가 유지해야 할 짐승이 될 것입니다. Regex와 같은 다른 솔루션을 찾는 것이 가장 좋습니다. &lt;.

다른 좋은 답변 외에도 조금 읽을 수 있습니다. 루프 불변 조금. 루프를 끝내기 위해 확인한 문자열에 물건을 넣고 다시 넣으면 모든 알람 벨을 설정해야합니다. :)

단지 추측이지만 이것은 범인과 같습니까? indexofinput = str.indexof (indexchars (i)) 'indexchar의 인스턴스 찾기

마이크로 소프트 문서, 반환 값 - 해당 문자열이 발견되면 값의 인덱스 위치 또는 그렇지 않은 경우 -1. 값이 비어 있으면 반환 값은 0입니다.

그래서 아마도 indexofinput이 0으로 설정되고 있습니까?

코드가 문자열을 청소하려고하면 어떻게됩니까? <a?

내가 읽을 때, 그것은 위치 0에서 indexchar를 찾지 만 indexnextleftbracket과 indexrightbracket은 모두 동일하게, 당신은 다른 조건에 빠지고, 위치 -1에 ">"를 삽입 할 것입니다. 당신에게 끈을 제공합니다 ><a. 새로운 IndexrightBracket은 0이되므로 0 자의 위치 0에서 0자가 삭제하여 ><a. 그런 다음 코드가 찾습니다 <a 코드에서 다시, 당신은 무한 메모리 소비 루프로 레이스를 떠납니다.

내가 틀렸더라도, 당신은 이러한 에지 케이스가 제대로 작동한다는 것을 스스로 확신시키기 위해 단위 테스트를 받아야합니다. 또한 오프베이스 인 경우 실제 루핑 코드를 찾는 데 도움이됩니다.

그러나 일반적 으로이 특정 버그를 고치더라도 결코 강력하지 않을 것입니다. Parsing HTML은 어렵고 HTML 블랙리스트는 항상 구멍이 생길 것입니다. 예를 들어, 내가 정말로 얻고 싶다면 <input type="hidden" name="tax" 태그를 넣으십시오 <input name="tax" type="hidden" 그리고 당신의 코드는 그것을 무시할 것입니다. 더 나은 내기는 실제 HTML 파서를 참여시키고 실제로 원하는 (매우 작은) 태그의 하위 집합 만 허용하는 것입니다. 또는 더 나은 방법으로 다른 형태의 마크 업을 사용하고 모든 HTML 태그를 제거하십시오 (다시 설명의 실제 HTML 파서를 사용하여).

실제 컴파일러를 통해 실행해야하지만 마인드 필러는 str = str.Remove(indexOfInput, indexRightBracket - indexOfInput) 라인은 유효하지 않은 태그를 다시 생성하여 다시 루프를 통해 동일한 실수를 발견하고 다시 시도하고 다시 시도하고 실수를 "고정"하는 것 등을 찾습니다.

fwiw는 문자열에서 원치 않는 HTML 태그를 제거하는 코드 스 니펫을 사용합니다 (C#이지만 개념은 번역)

public static string RemoveTags( string html, params string[] allowList )
{
    if( html == null ) return null;
    Regex regex = new Regex( @"(?<Tag><(?<TagName>[a-z/]+)\S*?[^<]*?>)",
                             RegexOptions.Compiled | 
                             RegexOptions.IgnoreCase | 
                             RegexOptions.Multiline );
    return regex.Replace( 
                   html, 
                   new MatchEvaluator( 
                       new TagMatchEvaluator( allowList ).Replace ) );
}

MatchEvaluator 클래스

private class TagMatchEvaluator
{
    private readonly ArrayList _allowed = null;

    public TagMatchEvaluator( string[] allowList ) 
    { 
        _allowed = new ArrayList( allowList ); 
    }

    public string Replace( Match match )
    {
        if( _allowed.Contains( match.Groups[ "TagName" ].Value ) )
            return match.Value;
        return "";
    }
}

그것은 단순한 일에 효과가없는 것 같습니다 <a<a<a 사례 또는 심지어 <a>Test</a>. 이것을 전혀 테스트 했습니까?

개인적으로, 나는 이렇게 문자열 구문 분석을 싫어합니다. 그래서 나는 당신의 오류가 어디에 있는지 알아 내지 않을 것입니다. 내가 기꺼이 넣는 것보다 디버거와 두통이 필요합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top