Jak kodować / dekodować jednostki HTML w Ruby?


200

Próbuję zdekodować niektóre elementy HTML, takie jak '&amp;lt;'stawanie się '<'.

Mam stary klejnot ( html_helpers ), ale wydaje się, że został porzucony dwukrotnie.

Jakieś rekomendacje? Będę musiał użyć go w modelu.


6
Właśnie znalazłem „htmlentities” ( htmlentities.rubyforge.org )
Kostas,

Powinienem określić, że otrzymuję html z wielu różnych stron i muszę zapisać go jako zwykły tekst w bazie danych
Kostas,

1
Podczas gdy najwięcej głosów oddano na korzystanie z CGI, nie rób tego. To tak, jakby wykorzystać całą Aktywną Pomoc, aby uzyskać jedną metodę. Zamiast tego użyj HTMLEntities, jak wspomniano w wybranej odpowiedzi.
Tin Man

Odpowiedzi:


153

HTMLEntities może to zrobić:

: 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. Dzięki za komentarz; rozwiązało to mój problem: Jak renderować odwołania do znaków XML w Ruby? także!
Josh Glover

4
Tak, HTMLEntitiesklejnot zajmuje się przypadkami takimi jak &aring;i &mdash;które CGI.unescapeHTMLnie.
thomax,

295

Aby zakodować znaki, możesz użyć CGI.escapeHTML:

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

Aby je zdekodować, dostępne są CGI.unescapeHTML:

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

Oczywiście wcześniej musisz dołączyć bibliotekę CGI:

require 'cgi'

A jeśli jesteś w Railsach, nie musisz używać CGI do kodowania łańcucha. Jest hmetoda.

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

9
Najpierw wypróbowałem to podejście, ale nie zmienia ono bytów takich jak „& nbsp;” w " ". Chyba powinienem sprecyzować, że otrzymuję html z wielu różnych stron i muszę zapisać go jako zwykły tekst w bazie danych.
Kostas

2
Jeśli dekodujesz encje HTML do przechowywania jako zwykły tekst w bazie danych, spodziewaj się, że baza danych narzeka na złe znaki. Zakodowane byty są kodowane, aby umożliwić im przesyłanie jako zwykły tekst. Dekodowanie ich może i najprawdopodobniej spowoduje przywrócenie ich do znaków o wyższych bitach, AKA binarnych. Prawie tak prawdopodobne, że możesz skończyć z wielobajtowymi znakami, które naprawdę drażnią DB, która oczekuje zwykłego tekstu. Lepiej dekoduj, dopóki nic się nie zmieni, a następnie koduj raz, aby wszystko zostało znormalizowane, a następnie zapisz je.
Tin Man

1
Zetknąłem się z wieloma kodami HTML z enkodami, które były wielokrotnie kodowane, robiąc bałagan. Sprawdź loofah ; Jego płuczki zostały zaprojektowane do tego, jeśli dobrze pamiętam.
Tin Man

3
Ustawiliśmy naszą bazę danych, aby oszczędzała Unicode, więc wątpię, czy w ogóle narzeka. Loofah nie jest tym, czego szukam, nie chcę pozbywać się tagów HTML - i tak nie w tym momencie.
Kostas

1
jest 2015, unescapeHTML wciąż pomija niektóre podmioty, takie jak A ostre
nurettin

47

Myślę, że klejnot Nokogiri to również dobry wybór. Jest bardzo stabilny i ma ogromną społeczność.

Próbki:

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

lub

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, tak, myślę, że to zależy od popytu. Jak widać w dyskusjach na ten temat, CGI.escapeHTMLbyć może nie uda się rozwiązać niektórych spraw. Z drugiej strony, jeśli potrzebujesz pełnego zestawu wsparcia, jestem pewien, że Nokogirito dobry wybór.
Hoang Le

6
Dodatkowo, jeśli już używasz Nokogiri do analizy składni HTML, nie ma sensu instalować kolejnego klejnotu wyłącznie w tym celu. Na przykład używam klejnotu Sanitize do czyszczenia HTML. Okazuje się, że ten klejnot używa Nokogiri pod maską i szkoda byłoby nie skorzystać z tego. Dzięki @HoangLe za wskazówkę!
Tomalla,

1
Uwaga: CGI::escapeHTMLnie ucieka przed niemieckimi postaciami, takimi jak äöüß, a może więcej ... Z Nokogiri jeszcze nie sprawdziłem, ale byłby to plus.
Piękno

HTMLEntities byłby lekkim i sprawnym wyborem. Często używam Nokogiri i, o ile już go nie załadowałem, wybrałbym HTMLEntities. CGI jest nieaktualny.
Tin Man

36

Aby zdekodować znaki w Railsach, użyj:

<%= raw '<html>' %>

Więc,

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

wyszedłby

<br>

5
Działa to jednak tylko w widoku. Potrzebuję też czegoś, co działa w ActiveRecord.
Kostas

3
Właśnie przetestowane w debuggerze - raw '& lt br & gt' ==> '& lt br & gt'.
Will Tomlins,

13
#rawniczego nie dekoduje. Mówi widokowi, aby nie kodował łańcucha. Odbywa się to poprzez zawijanie łańcucha w ActiveSupport::SafeBuffer, który z kolei ma flagę ( html_safe?), ustawioną na true. Widok używa tej flagi do ustalenia, że ​​ciąg może być wstrzykiwany bezpośrednio do HTML bez ucieczki. Lubię myśleć o html_safetym, że programista wskazuje, że omawiany ciąg znaków został już poprawnie zmieniony.
Moxley Stratton

9

Jeśli nie chcesz dodawać nowej zależności tylko po to, aby to zrobić (np. HTMLEntities), A już używasz Hpricot, może ona dla Ciebie zarówno uciec, jak i odinstalować. Obsługuje znacznie więcej niż CGI:

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

5
Uwaga dla osób, które teraz na to patrzą - Hpricot nie jest już utrzymywany.
SamStephens

2
Użyj Nokogiri , który jest standardem defacto dla parsowania XML / HTML, zamiast Hpricot.
Tin Man


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

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

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

Myślę, że dodając html_safe do dowolnego tekstu wprowadzonego przez użytkownika, mówisz widokowi, że jest bezpieczny, gdy jest możliwe, że nie jest bezpieczny. Naraziłoby to użytkowników na ryzyko, gdy załadują ten widok.
user1515295,

Nie wiem dlaczego tak negatywnie. Próbowałem wszystkich rozwiązań w tym pytaniu. Tylko to działa dobrze. O HTML bezpieczny, użytkownik chce renderować HTML, a następnie HTML_SAFE jest poprawny.
Diego Somar,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.