Nokogiri保持HTML实体不变

时间:2011-10-13 14:57:54

标签: ruby nokogiri

我希望Nokogiri保持HTML实体不变,但似乎是将实体转换为实际符号。例如:

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

结果为:"<p>®</p>"

似乎没有任何东西可以将原始HTML返回给我。 .inner_html,.text,.content方法都返回'®'而不是'&reg;'

Nokogiri有没有办法让这些HTML实体不受影响?

我已经搜索过stackoverflow并发现了类似的问题,但没有完全像这个问题。

感谢。

1 个答案:

答案 0 :(得分:18)

不是一个理想的答案,但您可以通过设置允许的编码来强制它生成实体(如果不是很好的名字):

#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>

如果Nokogiri使用定义的实体的“漂亮”名称,而不是总是使用简洁的十六进制实体,那将是很好的,但即使这样也不会“保留”原始实体。

问题的根源在于,在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">