2011-06-10 5 views
1

저는 이것이 문제가 해결 될만큼 일반적이라고 생각합니다.하지만 Loofah와 Nokogiri가있는 초심자 인 저는 아직 해결책을 찾지 못했습니다.텍스트에서 HTML을 벗겨 내고 Loofah와 Nokogiri로 자를 포함하고 있습니다.

Nokogiri를 감싸는 HTML 스크러버 라이브러리 인 Loofah를 사용하여 일부 HTML 텍스트를 스크럽하여 표시합니다. 그러나이 텍스트는 전자 메일 주소 등의 경우에 때로는 <> 사이의 문자 (예 : <[email protected]>)에서 발생합니다. 수세미는 HTML 또는 XML 태그로 생각하고 있으며 텍스트에서 제외합니다.

실제 태그를 제거하는 작업을 수행하면서 이러한 일이 발생하지 않도록하는 방법이 있습니까?

편집 : 여기 실패한 테스트 케이스의 :

require 'test/unit' 
require 'test/unit/ui/console/testrunner' 
require 'nokogiri' 

MAGICAL_REGEXP = /<([^(?:\/|!\-\-)].*)>/ 

def filter_html(content) 
    # Current approach in a gist: We capture content enclosed in angle brackets. 
    # Then, we check if the excerpt right after the opening bracket is a valid HTML 
    # tag. If it's not, we substitute the matched content (which is the captured 
    # content enclosed in angle brackets) for the captured content enclosed in 
    # the HTML entities for the angle brackets. This does not work with nested 
    # HTML tags, since regular expressions are not meant for this. 

    content.to_s.gsub(MAGICAL_REGEXP) do |excerpt| 
    capture = $1 
    Nokogiri::HTML::ElementDescription[capture.split(/[<> ]/).first] ? excerpt : "&lt;#{capture}&gt;" 
    end 
end 

class HTMLTest < Test::Unit::TestCase 
    def setup 
    @raw_html = <<-EOS 
<html> 
<[email protected]> 
<p><[email protected]<b class="highlight">bar</b>.baz></p> 
<p> 
<[email protected]<b class="highlight">bar</b>.baz> 
</p> 
< don't erase this > 
</html> 
EOS 

    @filtered_html = <<-EOS 
<html> 
&lt;[email protected]&gt; 
<p>&lt;[email protected]<b class="highlight">bar</b>.baz&gt;</p> 
<p> 
&lt;[email protected]<b class="highlight">bar</b>.baz&gt; 
</p> 
&lt; don't erase this &gt; 
</html> 
EOS 
    end 

    def test_filter_html 
    assert_equal(@filtered_html, filter_html(@raw_html)) 
    end 
end 

# Can you make this test pass? 
Test::Unit::UI::Console::TestRunner.run(HTMLTest) 

우리는 현재 시도하고 이러한 목표를 달성하기 위해 꽤 나쁜 정규식 해커를 사용하고 있지만, 상태 위의 주석으로,이 태그가 작동하지 않습니다 " 중첩 된 태그가 아닌 태그 내부. 실제로는 <b class="highlight"> 요소도 보존하려고합니다.

아래 샘플은 수세미를 사용하지 않지만 응용 프로그램 자체는 다른 곳에서 수행하므로 여기에 추가하기가 어렵지 않습니다. 우리는 어떤 구성 옵션을 사용해야하는지 확실하지 않습니다.

+1

텍스트에 실제로 "<"문자가 포함되어 있거나 "<"엔터티입니까? –

+1

문제를 표시하는 최소한의 스크립트 (입력 및 출력과 함께)를 제공하면 대답하기가 쉽습니다. –

+0

@ mark-thomas : 실패한 테스트 사례를 추가하기 위해 질문을 편집했습니다. 나는 그것이 문제에 대해 밝히기를 희망한다. – Bira

답변

2

주요 이슈는 Nokogiri가 완전히 망가 뜨린 HTML 엔터티 꺾쇠 괄호로 묶인 HTML 태그입니다. 우리는 HTML 태그를 제거하고 비 HTML 태그 꺾쇠 괄호를 이스케이프 처리 한 다음 HTML 태그가 다시 나타납니다. 그것은 약간 hackish 들리지만 완벽하게 작동합니다. 첫 번째 목표는 꺾쇠 괄호로 묶인 이메일 주소를 이스케이프 처리하는 것이었지만,이 방법은 모든 종류의 텍스트에서 작동합니다.

# Does not run on ruby 1.9 

require 'test/unit' 
require 'test/unit/ui/console/testrunner' 
require 'nokogiri' 
require 'active_support/secure_random' 

def filter_html(content) 
    # Used to mark highlighted words. 
    random_hex = SecureRandom.hex(6) 

    # Remove highlighting. 
    highlighted_terms = [] 
    without_highlighting = content.to_s.gsub(/<b class="highlight">(.*?)<\/b>/) do |match| 
    highlighted_terms << $1 
    "highlight-#{random_hex}:#{$1}" 
    end 

    # Escape non-HTML angle brackets. 
    escaped_content = without_highlighting.to_s.gsub(/<(?:\s*\/)?([^!\-\-].*?)>/) do |excerpt| 
    capture = $1 
    tag = capture.split(/[^a-zA-Z1-6]/).reject(&:empty?).first 
    !!Nokogiri::HTML::ElementDescription[tag] ? excerpt : "&lt;#{capture}&gt;" 
    end 

    # Add highlighting back. 
    highlighted_terms.uniq.each do |term| 
    escaped_content.gsub!(/highlight-#{random_hex}:(#{term})/) do |match| 
     "<b class=\"highlight\">#{$1}</b>" 
    end 
    end 

    escaped_content 
end 

class HTMLTest < Test::Unit::TestCase 
    def setup 
    @raw_html = <<-EOS 
     <html> 
     <[email protected]> 
     <p><[email protected]<b class="highlight">bar</b>.baz></p> 
     <p> 
      <[email protected]<b class="highlight">bar</b>.baz> 
     </p> 
     < don't erase this > 
     </html> 
    EOS 

    @filtered_html = <<-EOS 
     <html> 
     &lt;[email protected]&gt; 
     <p>&lt;[email protected]<b class="highlight">bar</b>.baz&gt;</p> 
     <p> 
      &lt;[email protected]<b class="highlight">bar</b>.baz&gt; 
     </p> 
     &lt; don't erase this &gt; 
     </html> 
    EOS 
    end 

    def test_filter_html 
    assert_equal(@filtered_html, filter_html(@raw_html)) 
    end 
end 

# It passes! 
Test::Unit::UI::Console::TestRunner.run(HTMLTest) 
+1

그렇게하는 것은 실제로 해킹이 아닙니다. 모든 프로그래밍 문제가 직설적이거나 우아한 방식으로 해결되는 것은 아닙니다. 특히 HTML과 XML을 다룰 때 그렇습니다. 때로는 더러워 져서 일을해야만하고, 어딘가에 가서 입안에서 맛을 내야합니다. 그것은 작업의 일부입니다. –

+0

무언가를 명확히하기 위해 : "주요 문제는 Nokogiri가 완전히 망가 뜨린 HTML 엔터티 꺾쇠 괄호로 묶인 HTML 태그입니다." Nokogiri는 HTML을 조작하지 않고 잘못된 형식의 마크 업이나 올바르게 닫히지 않은 태그를 닫거나 HTML이 사양을 충족하도록 포함을 조정하려고합니다. 'errors' 메서드를 사용하여 파싱 된 문서의 오류를보고 Nokogiri가 무엇을해야하는지 확인할 수 있습니다. 조작 된 HTML을 정리하기 위해 Nokogiri를 어떻게 사용하는지 예제를 보려면 http://stackoverflow.com/a/14515622/128421을 참조하십시오. –

관련 문제