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>

ノコギリはブロック<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 に答える