Bagaimana cara menyandikan / mendekodekan entitas HTML di Ruby?

200

Saya mencoba memecahkan kode beberapa entitas HTML, seperti '&amp;lt;'menjadi '<'.

Saya memiliki permata lama ( html_helpers ) tetapi tampaknya telah ditinggalkan dua kali.

Ada rekomendasi? Saya perlu menggunakannya dalam model.

Kostas
sumber
6
Baru saja menemukan 'htmlentities' ( htmlentities.rubyforge.org )
Kostas
Saya harus menentukan bahwa saya mendapatkan html dari banyak situs yang berbeda dan perlu menyimpannya sebagai teks biasa dalam database
Kostas
1
Sementara suara terbanyak digunakan untuk menggunakan CGI, jangan. Itu seperti menarik semua Dukungan Aktif untuk mendapatkan metode tunggal. Alih-alih, gunakan HTMLEntities, seperti yang disebutkan dalam jawaban yang dipilih.
the Tin Man

Jawaban:

153

HTMLEntities dapat melakukannya:

: 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!"
Ivailo Bardarov
sumber
Zdrasti Ivailo. Terima kasih atas komentar Anda; itu menyelesaikan masalah saya pada Bagaimana saya bisa membuat referensi entitas karakter XML di Ruby? demikian juga!
Josh Glover
4
Yup, HTMLEntitiespermata menangani kasus-kasus seperti &aring;dan &mdash;yang CGI.unescapeHTMLtidak.
thomax
295

Untuk menyandikan karakter, Anda dapat menggunakan CGI.escapeHTML:

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

Untuk memecahkan kode mereka, ada CGI.unescapeHTML:

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

Tentu saja, sebelum itu Anda perlu memasukkan perpustakaan CGI:

require 'cgi'

Dan jika Anda menggunakan Rails, Anda tidak perlu menggunakan CGI untuk menyandikan string. Itu hmetodenya.

<%= h 'escaping <html>' %>
Damien MATHIEU
sumber
9
Saya mencoba pendekatan ini terlebih dahulu tetapi tidak mengubah entitas seperti "& nbsp;" menjadi "". Saya kira saya harus menentukan bahwa saya mendapatkan html dari banyak situs yang berbeda dan perlu menyimpannya sebagai teks biasa dalam database.
Kostas
2
Jika Anda mendekode entitas HTML untuk penyimpanan sebagai teks biasa dalam database, maka harap database Anda melakukan banyak komplain tentang karakter buruk. Entitas yang dikodekan dikodekan untuk memungkinkan mereka mentransfer sebagai teks biasa. Mendekode mereka dapat, dan kemungkinan besar akan, mengembalikannya ke karakter set bit atas, AKA biner. Hampir mungkin, Anda bisa berakhir dengan karakter multibyte yang benar-benar akan mengganggu DB yang mengharapkan teks biasa. Sebaiknya Anda mendekode hingga tidak ada yang berubah, lalu disandikan sekali sehingga semuanya dinormalisasi, lalu simpan.
the Tin Man
1
Saya telah menemukan banyak HTML dengan entitas yang telah dikodekan beberapa kali, benar-benar membuat kekacauan. Lihatlah loofah ; Scrubber-nya dirancang untuk ini jika saya ingat benar.
the Tin Man
3
Kami telah mengatur basis data kami untuk menyimpan Unicode, jadi saya ragu itu akan mengeluh sama sekali. Dan loofah bukan yang saya cari, saya tidak ingin menyingkirkan tag html - toh pada saat ini tidak.
Kostas
1
ini tahun 2015, unescapeHTML masih menghilangkan beberapa entitas seperti A akut
nurettin
47

Saya pikir permata Nokogiri juga merupakan pilihan yang baik. Ini sangat stabil dan memiliki komunitas yang berkontribusi besar.

Sampel:

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

atau

a = Nokogiri::HTML.parse "&iexcl;I&#39;m highly&nbsp;annoyed with character references!"
a.text
=> "¡I'm highly annoyed with character references!"
Hoang Le
sumber
3
@ theTinMan, ya saya pikir itu tergantung pada permintaan. Seperti yang dapat Anda lihat melalui diskusi dalam topik ini, CGI.escapeHTMLmungkin tidak dapat menyelesaikan beberapa kasus. Di sisi lain, jika Anda membutuhkan dukungan penuh, saya yakin Nokogiriini adalah pilihan yang baik.
Hoang Le
6
Ditambah lagi jika Anda sudah menggunakan Nokogiri untuk beberapa parsing HTML, tidak masuk akal untuk menginstal permata lain hanya untuk tujuan itu. Misalnya, saya menggunakan permata Sanitize untuk membersihkan HTML. Ternyata permata ini menggunakan Nokogiri di bawah tenda dan jadi akan memalukan untuk tidak mengambil petualangan itu. Terima kasih @HoangLe untuk tipnya!
Tomalla
1
Catatan: CGI::escapeHTMLtidak luput dari karakter Jerman seperti äöüß, dan mungkin lebih ... Dengan Nokogiri saya belum memeriksanya, tetapi ini akan menjadi nilai tambah.
Kecantikan
HTMLEntities akan menjadi pilihan yang ringan dan mampu. Saya banyak menggunakan Nokogiri, dan, kecuali saya sudah memuatnya, saya akan menggunakan HTMLEntities. CGI kedaluwarsa.
the Tin Man
36

Untuk mendekode karakter dalam Rails gunakan:

<%= raw '<html>' %>

Begitu,

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

akan menghasilkan

<br>
memonk
sumber
5
Ini hanya berfungsi dalam tampilan sekalipun. Saya butuh sesuatu yang berfungsi di ActiveRecord juga.
Kostas
3
Baru diuji dalam debugger - raw '& lt br & gt' ==> '& lt br & gt'.
Will Tomlins
13
#rawtidak memecahkan kode apa pun. Ini memberitahu pandangan untuk tidak menyandikan string. Ini dilakukan dengan membungkus string dalam ActiveSupport::SafeBuffer, yang pada gilirannya memiliki flag ( html_safe?), disetel ke true. Tampilan menggunakan bendera ini untuk menentukan bahwa string dapat disuntikkan langsung ke dalam HTML tanpa melarikan diri. Saya suka menganggap html_safesebagai indikasi oleh programmer bahwa string tersebut telah benar-benar lolos.
Moxley Stratton
9

Jika Anda tidak ingin menambahkan dependensi baru hanya untuk melakukan ini (seperti HTMLEntities) dan Anda sudah menggunakan Hpricot, itu bisa melarikan diri dan menghapus untuk Anda. Ini menangani lebih dari CGI:

Hpricot.uxs "foo&nbsp;b&auml;r"
=> "foo bär"
Jason L Perry
sumber
5
Catatan untuk orang-orang yang melihat ini sekarang - Hpricot tidak lagi dikelola.
SamStephens
2
Gunakan Nokogiri , yang merupakan standar defacto untuk parsing XML / HTML, bukan Hpricot.
the Tin Man
0

Anda bisa menggunakan htmlasciipermata:

Htmlascii.convert string
kartouch
sumber
-5
<% str="<h1> Test </h1>" %>

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

<%= CGI.unescapeHTML(str).html_safe %>
Usman
sumber
Saya berpikir bahwa dengan menambahkan html_safe pada teks yang dimasukkan pengguna, Anda memberi tahu pandangan bahwa itu aman ketika mungkin tidak aman. Ini akan menempatkan pengguna Anda dalam risiko ketika mereka memuat tampilan itu.
user1515295
Saya tidak tahu mengapa sangat negatif. Saya mencoba semua solusi dalam pertanyaan ini. Hanya ini yang berfungsi. Tentang HTML safe, pengguna INGIN merender HTML, lalu HTML_SAFE benar.
Diego Somar