ฉันจะเข้ารหัส / ถอดรหัสเอนทิตี HTML ใน Ruby ได้อย่างไร


200

ฉันพยายามที่จะถอดรหัสหน่วยงาน HTML บางอย่างเช่นการเป็น'&amp;lt;''<'

ฉันมีอัญมณีเก่าแก่ ( html_helpers ) แต่ดูเหมือนว่ามันจะถูกละทิ้ง

คำแนะนำใด ๆ ฉันจะต้องใช้มันในแบบจำลอง


6
เพิ่งพบ 'htmlentities' ( htmlentities.rubyforge.org )
Kostas

ฉันควรระบุว่าฉันได้รับ html จากเครือต่าง ๆ ของไซต์และจำเป็นต้องบันทึกเป็นข้อความธรรมดาในฐานข้อมูล
Kostas

1
ในขณะที่คะแนนโหวตส่วนใหญ่ไปใช้ CGI ไม่ นั่นเหมือนกับการดึงใน Active Support ทั้งหมดเพื่อรับวิธีการเดียว ใช้ HTMLEntities แทนดังที่กล่าวไว้ในคำตอบที่เลือก
ชายดีบุก

คำตอบ:


153

HTMLEntitiesสามารถทำได้:

: jmglov@laurana; sudo gem install htmlentities
Successfully installed htmlentities-4.2.4
: jmglov@laurana;  irb
irb(main):001:0> require 'htmlentities'
=> []
irb(main):002:0> HTMLEntities.new.decode "&iexcl;I&#39;m highly&nbsp;annoyed with character references!"
=> "¡I'm highly annoyed with character references!"

Zdrasti Ivailo ขอบคุณสำหรับความคิดเห็นของคุณ แก้ไขปัญหาของฉันบนฉันจะแสดงการอ้างอิงเอนทิตีอักขระ XML ใน Ruby ได้อย่างไร เช่นกัน!
Josh Glover

4
ใช่HTMLEntitiesพลอยเกี่ยวข้องกับคดีเช่น&aring;และ&mdash;ที่CGI.unescapeHTMLไม่
thomax

295

หากต้องการเข้ารหัสอักขระคุณสามารถใช้CGI.escapeHTML:

string = CGI.escapeHTML('test "escaping" <characters>')

เพื่อถอดรหัสพวกเขามีCGI.unescapeHTML:

CGI.unescapeHTML("test &quot;unescaping&quot; &lt;characters&gt;")

แน่นอนว่าก่อนหน้านี้คุณต้องรวมไลบรารี CGI:

require 'cgi'

และถ้าคุณอยู่ใน Rails คุณไม่จำเป็นต้องใช้ CGI เพื่อเข้ารหัสสตริง มีhวิธีการคือ

<%= h 'escaping <html>' %>

9
ฉันลองใช้วิธีนี้ก่อน แต่ไม่เปลี่ยนเอนทิตีเช่น "& nbsp;" เป็น "" ฉันเดาว่าฉันควรจะระบุว่าฉันได้รับ html จากหลาย ๆ ไซต์และต้องบันทึกเป็นข้อความธรรมดาในฐานข้อมูล
Kostas

2
หากคุณกำลังถอดรหัสเอนทิตี HTML สำหรับการจัดเก็บเป็นข้อความธรรมดาในฐานข้อมูลแล้วคาดว่าฐานข้อมูลของคุณจะบ่นเกี่ยวกับตัวละครที่ไม่ดี เอนทิตีที่เข้ารหัสจะถูกเข้ารหัสเพื่อให้สามารถถ่ายโอนเป็นข้อความธรรมดา การถอดรหัสพวกมันสามารถและเปลี่ยนกลับไปเป็นตัวละคร AKA ไบนารี เกือบจะเป็นไปได้ที่คุณจะจบลงด้วยอักขระหลายไบต์ซึ่งจะทำให้ DB ที่คาดหวังข้อความธรรมดาน่ารำคาญ คุณดีกว่าการถอดรหัสจนกว่าจะไม่มีอะไรเปลี่ยนแปลงจากนั้นเข้ารหัสหนึ่งครั้งเพื่อให้ทุกอย่างเป็นปกติแล้วเก็บไว้
Tin Man

1
ฉันพบ HTML จำนวนมากที่มีเอนทิตีที่ถูกเข้ารหัสหลายครั้งทำให้ยุ่งเหยิงจริงๆ ตรวจสอบรังบวบ ; ตัวขัดมันถูกออกแบบมาสำหรับสิ่งนี้ถ้าฉันจำได้ถูกต้อง
Tin Man

3
เราได้ตั้งค่าฐานข้อมูลของเราเพื่อบันทึก Unicode ดังนั้นฉันสงสัยว่ามันจะบ่นเลย และรังบวบไม่ใช่สิ่งที่ฉันกำลังมองหาฉันไม่ต้องการกำจัดแท็ก html - ไม่ใช่ตอนนี้
Kostas

1
มันเป็นในปี 2015 ยังคง unescapeHTML ละเว้นบางส่วนของหน่วยงานเช่น A เฉียบพลัน
Nurettin

47

ฉันคิดว่าอัญมณี Nokogiriเป็นทางเลือกที่ดีเช่นกัน มันมีเสถียรภาพมากและมีชุมชนที่ให้ความช่วยเหลือเป็นอย่างมาก

ตัวอย่าง:

a = Nokogiri::HTML.parse "foo&nbsp;b&auml;r"    
a.text 
=> "foo bär"

หรือ

a = Nokogiri::HTML.parse "&iexcl;I&#39;m highly&nbsp;annoyed with character references!"
a.text
=> "¡I'm highly annoyed with character references!"

3
@TheTinMan ใช่ฉันคิดว่ามันขึ้นอยู่กับความต้องการ อย่างที่คุณเห็นผ่านการอภิปรายในหัวข้อนี้CGI.escapeHTMLอาจจะไม่สามารถแก้ไขบางกรณี ในทางกลับกันหากคุณต้องการการสนับสนุนอย่างเต็มที่ฉันมั่นใจว่าNokogiriเป็นตัวเลือกที่ดี
Hoang Le

6
นอกจากนี้หากคุณใช้ Nokogiri อยู่แล้วในการแยกวิเคราะห์ HTML มันก็ไม่มีเหตุผลที่จะติดตั้งอีกอันสำหรับอัญมณีนั้นเพื่อจุดประสงค์นั้น ตัวอย่างเช่นฉันใช้ Sanitize gem เพื่อล้าง HTML กลับกลายเป็นว่าอัญมณีนี้กำลังใช้ Nokogiri อยู่ใต้กระโปรงหน้ารถดังนั้นมันจึงเป็นเรื่องน่าละอายที่จะไม่เสี่ยงกับสิ่งนั้น ขอบคุณ @HangangLe สำหรับเคล็ดลับ!
Tomalla

1
หมายเหตุ: CGI::escapeHTMLไม่รอดพ้นตัวละครเยอรมันเช่นäöüßและอาจจะมากกว่านั้น ... กับ Nokogiri ฉันยังไม่ได้ตรวจสอบ แต่นี่จะเป็นจุดบวก
ความงาม

HTMLEntities จะเป็นตัวเลือกที่เบาและมีความสามารถ ฉันใช้ Nokogiri มากและถ้าฉันโหลดเสร็จแล้วฉันจะไปกับ HTMLEntities CGI ล้าสมัย
ชายดีบุก

36

ในการถอดรหัสอักขระใน Rails ให้ใช้:

<%= raw '<html>' %>

ดังนั้น,

<%= raw '&lt;br&gt;' %>

จะส่งออก

<br>

5
วิธีนี้ใช้งานได้ในมุมมองเท่านั้น ฉันต้องการบางสิ่งที่ทำงานใน ActiveRecord ด้วย
Kostas

3
เพิ่งทดสอบในเครื่องมือดีบั๊ก - raw '& lt br & gt' ==> '& lt br & gt'
Tomlins จะ

13
#rawไม่ได้ถอดรหัสอะไรเลย มันบอกมุมมองที่จะไม่เข้ารหัสสตริง มันทำได้โดยการตัดสตริงใน a ActiveSupport::SafeBufferซึ่งจะมีค่าสถานะ ( html_safe?) ตั้งค่าเป็นจริง มุมมองใช้การตั้งค่าสถานะนี้เพื่อตรวจสอบว่าสายอักขระสามารถถูกฉีดเข้าไปใน HTML โดยตรงโดยไม่ถูก Escape ฉันชอบคิดว่าhtml_safeเป็นข้อบ่งชี้ของโปรแกรมเมอร์ว่าสตริงที่เป็นปัญหาได้ถูกหลบหนีอย่างเหมาะสมแล้ว
Moxley Stratton

9

หากคุณไม่ต้องการที่จะเพิ่มการพึ่งพาใหม่เพียงเพื่อทำสิ่งนี้ (เช่นHTMLEntities) และคุณใช้อยู่แล้วHpricotมันสามารถหลบหนีและไม่ได้ทิวทัศน์สำหรับคุณ มันจัดการได้มากกว่าCGI:

Hpricot.uxs "foo&nbsp;b&auml;r"
=> "foo bär"

5
หมายเหตุสำหรับคนที่กำลังดูสิ่งนี้ในตอนนี้ - Hpricot ไม่ได้รับการดูแลรักษาอีกต่อไป
SamStephens

2
ใช้Nokogiriซึ่งเป็นมาตรฐาน defacto สำหรับการแยกวิเคราะห์ XML / HTML แทน Hpricot
คนดีบุก


-5
<% str="<h1> Test </h1>" %>

result: &lt; h1 &gt; Test &lt; /h1 &gt;

<%= CGI.unescapeHTML(str).html_safe %>

ฉันคิดว่าการเพิ่ม html_safe ในข้อความที่ป้อนโดยผู้ใช้คุณกำลังบอกมุมมองว่าปลอดภัยเมื่อเป็นไปได้ว่าไม่ปลอดภัย นี่จะทำให้ผู้ใช้ของคุณตกอยู่ในความเสี่ยงเมื่อพวกเขาโหลดมุมมองนั้น
user1515295

ฉันไม่รู้ว่าทำไมลบ ฉันลองวิธีแก้ปัญหาทั้งหมดในคำถามนี้ ใช้งานได้ดีเท่านั้น เกี่ยวกับ HTML ที่ปลอดภัยผู้ใช้ต้องการ WANTS เพื่อแสดง HTML และ HTML_SAFE นั้นถูกต้อง
Diego Somar
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.