Не идеальный ответ, но вы можете заставить его генерировать сущности (если не хорошие имена), установив допустимую кодировку:
#encoding: UTF-8
require 'nokogiri'
html = Nokogiri::HTML.fragment('<p>®</p>')
puts html.to_html #=> <p>®</p>
puts html.to_html( encoding:'US-ASCII' ) #=> <p>®</p>
Было бы неплохо, если бы Нокогири использовал «хорошие» имена сущностей, где они определены, вместо того, чтобы всегда использовать краткую шестнадцатеричную сущность, но даже это не будет «сохранять» оригинал.
Корень проблемы в том, что в HTML все следующее описание описывает одно и то же содержание:
<p>®</p>
<p>®</p>
<p>®</p>
<p>®</p>
Если вы хотите, чтобы to_s
представление текстового узла было на самом деле ®
, тогда разметка, описывающая это, будет действительно: <p>&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®</p>
Однако я не могу найти способ заставить их создаваться во время синтаксического анализа с использованием Nokogiri v1.4.4 или v1.5.0. В частности, наличие или отсутствие Nokogiri::XML::ParseOptions::NOENT
во время синтаксического анализа, по-видимому, не приводит к его созданию:
require 'nokogiri'
html = "<p>Foo®</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">