我有这样的代码:
doc = Nokogiri::HTML.fragment(html)
doc.to_html
以及将被解析的HTML片段:
<p>some paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
<code>
<html>
<p>
qwerty
</p>
</html>
</code>
<p>some other paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
Nokogiri删除<code>
块中的<html>
</html>
标签。如何防止这种行为?
更新:
Tin Man提出的解决方案,预解析html片段并在代码块中转义所有html
这里有一些代码,它不漂亮,所以如果你想建议另一个解决方案,请发表评论
html.gsub!(/<codeb[^>]*>(.*?)</code>/m) do |x|
"<code>#{CGI.escapeHTML($1)}</code>"
end
感谢铁皮人
问题是HTML无效。我用这个来测试它:
require 'nokogiri'
doc = Nokogiri::HTML::DocumentFragment.parse(<<EOT)
<p>some paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
<code>
<html>
<p>
qwerty
</p>
</html>
</code>
<p>some other paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
EOT
puts doc.errors
解析文档后,Nokogiri将用解析过程中发现的错误列表填充errors
数组。就HTML而言,doc.errors
包含:
htmlParseStartTag: misplaced <html> tag
原因是,在<code>
块中,标签没有按照应有的方式进行HTML编码
使用HTML实体将其转换为:
<html>
<p>
qwerty
</p>
</html>
它会起作用的。
Nokogiri是一个XML/HTML解析器,它试图修复标记中的错误,让程序员有很好的机会使用文档。在这种情况下,因为<html>
块位于错误的位置,所以它会删除标记。Nokogiri不会在意标签是否被编码,因为在这一点上,它们只是文本,而不是标签。
编辑:
我将尝试使用gsub进行预解析,并在代码块中转换html
require 'nokogiri'
html = <<EOT
<p>some paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
<code>
<html>
<p>
qwerty
</p>
</html>
</code>
<p>some other paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
EOT
doc = Nokogiri::HTML::DocumentFragment.parse(html.gsub(%r[<(/?)html>], '<1html>'))
puts doc.to_html
哪个输出:
<p>some paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
<code>
<html>
<p>
qwerty
</p>
</html>
</code>
<p>some other paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
编辑:
这将在解析之前处理<html>
标记,因此Nokogiri可以毫发无损地加载<code>
块。然后,它找到<code>
块,取消对编码的<html>
开始和结束标签的注释,然后将生成的文本作为其内容插入到<code>
块中。因为它是作为内容插入的,所以当Nokogiri将DOM呈现为HTML时,文本在必要时被重新编码为实体:
require 'cgi'
require 'nokogiri'
html = <<EOT
<p>some paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
<code>
<html>
<p>
qwerty
</p>
</html>
</code>
<p>some other paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
EOT
doc = Nokogiri::HTML::DocumentFragment.parse(html.gsub(%r[<(/?)html>], '<1html>'))
code = doc.at('code')
code.content = CGI::unescapeHTML(code.inner_html)
puts doc.to_html
哪个输出:
<p>some paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
<code>
<html>
<p>
qwerty
</p>
</html>
</code>
<p>some other paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>