1

我有这样的代码:

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 删除块<html> </html>中的标签<code>。如何防止这种行为?

更新:

Tin Man提出的解决方案,预解析 html 片段并转义代码块中的所有 html

这里有一些代码,它并不漂亮,所以如果您想提出其他解决方案,请发表评论

html.gsub!(/<code\b[^>]*>(.*?)<\/code>/m) do |x|
  "<code>#{CGI.escapeHTML($1)}</code>"
end

感谢铁皮人

4

1 回答 1

3

问题是 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 实体将其转换为:

&lt;html&gt;
    &lt;p&gt;
        qwerty
    &lt;/p&gt;
&lt;/html&gt;

它会起作用。

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>], '&lt;\1html&gt;'))

puts doc.to_html

哪个输出:

<p>some paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
<code>
    &lt;html&gt;
        <p>
            qwerty
        </p>
    &lt;/html&gt;
</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>], '&lt;\1html&gt;'))

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>
    &lt;html&gt;
        &lt;p&gt;
            qwerty
        &lt;/p&gt;
    &lt;/html&gt;
</code>
<p>some other paragraph</p>
<a href="https://url...com"><span style="color: #a5a5a5;"><i>qwerty</i></span> ytrewq </a>
于 2013-02-12T15:28:47.343 回答