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.