Нокогири, оставив HTML-сущности нетронутыми - PullRequest
16 голосов
/ 13 октября 2011

Я хочу, чтобы Nokogiri оставил нетронутыми сущности HTML, но похоже, что они преобразовывают сущности в реальный символ.Например:

 Nokogiri::HTML.fragment('<p>&reg;</p>').to_s

приводит к: "<p>®</p>"

Ничто не может вернуть мне исходный HTML.Все методы .inner_html, .text, .content возвращают '®' вместо '&reg;'

Можно ли в Nokogiri оставить эти объекты HTML без изменений?

Я уже искалstackoverflow и нашел похожие вопросы, но ничего такого, как этот.

Спасибо.

1 Ответ

18 голосов
/ 14 октября 2011

Не идеальный ответ, но вы можете заставить его генерировать сущности (если не хорошие имена), установив допустимую кодировку:

#encoding: UTF-8
require 'nokogiri'
html = Nokogiri::HTML.fragment('<p>&reg;</p>')
puts html.to_html                              #=> <p>®</p>
puts html.to_html( encoding:'US-ASCII' )       #=> <p>&#174;</p>

Было бы неплохо, если бы Нокогири использовал «хорошие» имена сущностей, где они определены, вместо того, чтобы всегда использовать краткую шестнадцатеричную сущность, но даже это не будет «сохранять» оригинал.

Корень проблемы в том, что в HTML все следующее описание описывает одно и то же содержание:

<p>®</p>
<p>&reg;</p>
<p>&#xAE;</p>  
<p>&#174;</p>

Если вы хотите, чтобы to_s представление текстового узла было на самом деле &reg;, тогда разметка, описывающая это, будет действительно: <p>&amp;reg;</p>.

Если бы Nokogiri всегда возвращал одну и ту же кодировку на символ, которая использовалась для ввода документа, он должен был бы хранить каждый символ в качестве пользовательского узла, записывающего ссылку на сущность. Существует класс, который может быть использован для этого (Nokogiri::XML::EntityReference):

require 'nokogiri'
html = Nokogiri::HTML.fragment("<p>Foo</p>")
html.at('p') << Nokogiri::XML::EntityReference.new( html.document, 'reg' )
puts html
#=> <p>Foo&reg;</p>

Однако я не могу найти способ заставить их создаваться во время синтаксического анализа с использованием Nokogiri v1.4.4 или v1.5.0. В частности, наличие или отсутствие Nokogiri::XML::ParseOptions::NOENT во время синтаксического анализа, по-видимому, не приводит к его созданию:

require 'nokogiri'
html = "<p>Foo&reg;</p>"
[ Nokogiri::XML::ParseOptions::NOENT,
  Nokogiri::XML::ParseOptions::DEFAULT_HTML,
  Nokogiri::XML::ParseOptions::DEFAULT_XML,
  Nokogiri::XML::ParseOptions::STRICT
].each do |parse_option|
  p Nokogiri::HTML(html,nil,'utf-8',parse_option).at('//text()')
end
#=> #<Nokogiri::XML::Text:0x810cca48 "Foo\u00AE">
#=> #<Nokogiri::XML::Text:0x810cc624 "Foo\u00AE">
#=> #<Nokogiri::XML::Text:0x810cc228 "Foo\u00AE">
#=> #<Nokogiri::XML::Text:0x810cbe04 "Foo\u00AE">
...