5

<p>タグ間の HTML フラグメントから空白を削除しようとしています

<p>Foo Bar</p> <p>bar bar bar</p> <p>bla</p>

<p> </p>ご覧のとおり、タグの間には常に空白があります。

<br>問題は、文字列をデータベースに保存するときに空白がタグを作成することです。ノード内の空白を削除するか、stripまたは削除するだけのメソッドにより、次の結果が得られます。gsub

<p>FooBar</p> <p>barbarbar</p> <p>bla</p>

私がしたいのに対し:

<p>Foo Bar</p><p>bar bar bar</p><p>bla</p>

私は使用しています:

  • のこぎり1.5.6
  • ルビー1.9.3
  • レール

アップデート:

時折<p>、同じ問題を生成するタグの子ノードがあります: 間に空白があります。

サンプルコード

注: コードは通常 1 行です。そうしないと耐えられないので、再フォーマットしました...

<p>
  <p>
    <strong>Selling an Appartment</strong>
  </p>
  <ul>
    <li>
      <p>beautiful apartment!</p>
    </li>
    <li>
      <p>near the train station</p>
    </li>
    .
    .
    .
  </ul>
  <ul>
    <li> 
      <p>10 minutes away from a shopping mall </p>
    </li>
    <li>
      <p>nice view</p>
    </li>
  </ul>
  .
  .
  .
</p>

これらの空白も削除するにはどうすればよいですか?

解決

メソッドの使用を台無しにして、withgsubを使用する可能性をさらに調査しなかったことが判明しました...gsubregex

簡単な解決策は追加でした

data = data.gsub(/>\s+</, "><")

さまざまな種類のノード間の空白をすべて削除しました...正規表現です!

4

4 に答える 4

2

これは私がコードを書く方法です:

require 'nokogiri'

doc = Nokogiri::HTML::DocumentFragment.parse(<<EOT)
<p>Foo Bar</p> <p>bar bar bar</p> <p>bla</p>
EOT

doc.search('p, ul, li').each { |node| 
  next_node = node.next_sibling
  next_node.remove if next_node && next_node.text.strip == ''
}

puts doc.to_html

結果は次のとおりです。

<p>Foo Bar</p><p>bar bar bar</p><p>bla</p>

それを分解する:

doc.search('p')

<p>ドキュメント内のノードのみを検索します。Nokogiri は から NodeSet を返すsearchか、何も一致しない場合は nil を返します。コードは NodeSet をループし、各ノードを順番に調べます。

next_node = node.next_sibling

現在のノードに続く次のノードへのポインタを取得し<p>ます。

next_node.remove if next_node && next_node.text.strip == ''

next_node.removenext_node次のノードが nil ではなく、削除されたときにそのテキストが空でない場合、つまり、ノードに空白しかない場合、現在のノードを DOM から削除します。

ドキュメントからすべての TextNode を削除する必要がある場合は、TextNode のみを検索する方法が他にもあります。タグ間のすべての空白を削除してしまう可能性があり、ランオン センテンスや結合された単語が発生する可能性があるため、これは危険です。

于 2013-05-07T19:59:37.653 に答える
0

出力の解析で不要な空白 (Unicode を含む) を処理する、探している可能性のあるすべてのタスクを次に示します。

html = "<p>A paragraph.<em>&nbsp; &nbsp;</em> <br><br><em>&nbsp; &nbsp; &nbsp; 
</em></p><p><em>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </em>
</p><p><em>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 
&nbsp; &nbsp;&nbsp; </em><strong><em>\" Quoted Text \"&nbsp; </em></strong></p>
<ul><li><p>List 1</p></li><li><p>List 2</p></li><li><p>List 3 </p>
<p><br></p><p><br><em> &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</em><br>
A text content.<br><em><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </em></p></li></ul>"

doc = Nokogiri::HTML.fragment(html)

doc.traverse { |node|
  # removes any whitespace node
  node.remove if node.text.gsub(/[[:space:]]/, '') == ''

  # replace mutiple consecutive spaces with single space
  node.content = node.text.gsub(/[[:space:]]{2,}/, ' ') if node.text?
}

# Gives you html without any text node including <br> or multiple spaces anywhere in the text of html
puts doc.to_html

# Gives text of html, concatenating li items with a space between them
# By default li items text are concatenated without the space     
Nokogiri::HTML(doc.to_html).xpath('//text()').map(&:text).join(' ')

#Output 
# "A paragraph. \" Quoted Text \"  \n List 1 \n List 2 \n \n List 3  \n A text content. \n \n"

# To Remove newline character '\n'
Nokogiri::HTML(doc.to_html).xpath('//text()').map(&:text).join(' ').gsub(/\n+/,'')

#Output
# "A paragraph. \" Quoted Text \"   List 1  List 2   List 3   A text content."

注:fragment完全なドキュメントの場合に使用していない場合は、などの他の関数htmlに置き換える必要がある場合があります。traversesearch

于 2021-01-06T10:30:17.257 に答える
-3

data.squish は同じことを行い、読みやすくなっています。

于 2016-05-16T21:08:07.873 に答える