1

HTML ドキュメントを処理し、いくつかのノードをいくつかの場所に挿入する必要があります。私が処理しているコンテンツは有効ではありませんが、ノコギリはそれがどうあるべきかを理解するのに十分賢いです. 問題は、挿入する部分以外は、元のドキュメントの書式を変更したくないということです。

次に例を示します。

require 'nokogiri'

orig_html = '
  <html>
  <meta name="Generator" content="Microsoft Word 97 O.o">
  <body>
    1
    <b><p>2</p></b>
    3
  </body>
</html>'

puts Nokogiri::HTML(orig_html).inner_html

# >> <html>
# >> <head>
# >> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
# >> <meta name="Generator" content="Microsoft Word 97 O.o">
# >> </head>
# >> <body>
# >>         1
# >>         <b></b><p>2</p>
# >>         3
# >>       </body>
# >> </html>

インプットとアウトプットを同じにしたい。問題は、 の中に入れられないこと<p>です<b>。私の傾向は XML に切り替えることですが、タグなどの無効なタグがあり、<meta>閉じられていません。HTML はこれを認識できるほどスマートですが、XML はそうではありません。

4

2 に答える 2

2

Nokogiri は、不正な形式の HTML を解析可能にするために修正しています。終了後、DOM は適切な状態になりますが、元のドキュメントは Nokogiri から入手できなくなります。

オリジナルを変更しない場合は、Nokogiri に渡す前に有効にする必要があります。その後、Nokogiri のメソッドを使用して操作できます。通常、正規表現を使用して問題のある場所を見つけ、タグまたは関連する終了タグを追加/調整して、Nokogiri が問題を修正することなく解析できるようにします。

errorsこれは、HTML が XML よりも優れているということではありません。厳格な XML 仕様の精神を尊重し、ファイルが無効な場合に配列にエラーを入力してフラグを立てる Nokogiri の事例です。HTML の仕様はそれほど厳格ではありません。ブラウザーは HTML を解析して表示する際に (あまりにも) 寛容であるため、Nokogiri はある程度それに従い、修正を行い、errors配列に値を入力します。(どちらの場合でも、その配列をチェックして何が問題なのかを確認できます。)

require 'nokogiri'

orig_html = '
  <html>
  <meta name="Generator" content="Microsoft Word 97 O.o">
  <body>
    1
    <b><p>2</p></b>
    3
  </body>
</html>'

doc = Nokogiri::HTML(orig_html)
doc.errors

doc.errors内容:

[
    [0] #<Nokogiri::XML::SyntaxError: Unexpected end tag : b>
]

Nokogiri を使用してサンプル HTML を修正する方法は次のとおりです。

doc = Nokogiri::HTML(orig_html)
p = doc.at('b+p')
p.previous_sibling.remove

この時点での HTML は次のとおりです。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="Generator" content="Microsoft Word 97 O.o">
</head>
<body>
    1
    <p>2</p>
    3
  </body>
</html>

続き:

p.inner_html = "<b>#{p.content}</b>"
puts doc.to_html

結果の HTML は次のとおりです。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="Generator" content="Microsoft Word 97 O.o">
</head>
<body>
    1
    <p><b>2</b></p>
    3
  </body>
</html>

サンプル HTML が実際に作業しているものではないことは明らかなので、変更が必要なタグを見つけるためにアクセサーを変更する必要がありますが、それでうまくいくはずです。

于 2013-01-25T04:59:49.993 に答える
0

上記は上記の特定の状況では機能しますが、以下のような場合には機能しません。

    orig_html = '
      <html>
      <meta name="Generator" content="Microsoft Word 97 O.o">
      <body>
        1
        <b>this is a bold
          <p>This is a paragraph</p>
        </b>
        3
      </body>
    </html>'

    doc = Nokogiri::HTML(orig_html)
    p = doc.at('b+p')

    p.previous_sibling.remove
    p.inner_html = "<b>#{p.content}</b>" # !> mismatched indentations at 'end' with 'def' at 17
     puts doc.to_html

結果の HTML:

   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="Generator" content="Microsoft Word 97 O.o">
    </head>
    <body>
        1
         <p><b>This is a paragraph</b></p>

        3
      </body>
    </html>
于 2013-01-25T22:30:32.110 に答える