2

私はいくつかのHTMLを持っています:

<p>Lorem ipsum example laoreet. <a href="#">example</a>Cum porttitor</p>
<p>Phasellus <a href="#">gravida tempor example</a> magna</p>

アンカータグ内にない限り、HTML で発生するテキスト「例」のインスタンスをスパンでラップする必要があります。したがって、上記は次のようになります。

<p>Lorem ipsum <span class="something">example</span> laoreet. <a href="#">example</a>Cum porttitor</p>
<p>Phasellus <a href="#">gravida tempor example</a> posuere. Fusce vitae urna eu <span class="something">example</span> magna</p>

次を使用して、アンカータグ内にない段落のコンテンツを選択できます。

doc.xpath('//p//text()') - doc.xpath('//p//a/text()')

次を使用して、別のタグのテキスト コンテンツをタグで囲むことができます。

doc.search('div.some-class text()').wrap('<span class="something"></span>')

しかし、そのコンテンツ内のテキストをタグで囲むにはどうすればよいでしょうか?

4

4 に答える 4

1

text()Xpath セレクターを使用して、次のようにテキストを照合することもできます: Using
XPath, How do I select a node based on its text content and value of an attribute?

doc.xpath("//p//text()='example'")

しかし、私はこれがうまくいくとは思わない:

doc.search("div.some-class text()='example'").wrap('<span class="something"></span>')
于 2013-08-14T11:54:41.400 に答える
1

問題のテキスト ノードを Ruby で操作してから、replaceNokogiri が解析する新しいテキストを含むドキュメント内で操作する必要があります。

doc.xpath('//p/descendant-or-self::node()[name() != "a"]/text()[contains(., "example")]').each do |n|
  n.replace(n.content.gsub(/(example)/, '<span class="something">\1</span>'))
end

この例では、あなたよりも少し複雑な XPath クエリを使用しています。要素の子孫でない限りp、任意の要素のすべてのテキストノードの子孫を選択します。これはあなたが望むものだと思います。(これがあなたにとってより良いかどうかはわかりません。試してみてください。)a

あなたの質問に答えるビットは、ブロックの内容です。ここでは、これらの各テキスト ノードの文字列コンテンツを取得し、新しい要素を含むgsubマークアップの新しい文字列を作成するために使用します。次に、このフラグメントをドキュメント内の元のテキスト ノードの代わりに配置します。Nokogiri はこの文字列を解析し、作成されたノードを元のテキスト ノードの代わりに追加します。これは多くの点でTin Man の回答に似ていますが、問題のテキスト ノードを使用して再解析するだけであるため、より的を絞っています。spanreplacegsub

于 2013-08-14T16:59:44.500 に答える
0

これが私が最終的にそれをした方法です:

doc = Nokogiri::HTML(html)
# Select paragraph content that isn't inside an anchor tag
elements = doc.xpath('//p//text()') - doc.xpath('//p//a/text()')
# interate over the elements, wrapping 'phrase' with anchor tag
elements.each do |element|
    element.content = element.content.gsub(phrase, "<a href='#' class='glossary-term-link' data-content='#{definition.html_safe}'>#{phrase}</a>")
end
# Fix Nokogiri's lust for escaping angle brackets no matter what
doc.xpath('//body')[0].inner_html.gsub("&lt;", "<").gsub("&gt;", ">")
于 2013-08-14T18:11:32.037 に答える
0

これが私がそれを行う方法です:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<p>Lorem ipsum example sit amet. <a href="#">example</a>Sed porttitor</p>
<p>Phasellus <a href="#">tempor example</a> posuere. Example </p>
EOT

a_tags = doc.search('a')

new_doc = Nokogiri::HTML(
  doc.to_html.gsub(
    /\b (example) \b/ix,
    '<span class="foo">\1</span>'
  )
)
new_doc.search('a').each do |a_tag|
  a_tag.replace(a_tags.shift)
end

puts new_doc.to_html
# >> </body></html>
# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html><body>
# >> <p>Lorem ipsum <span class="foo">example</span> sit amet. <a href="#">example</a>Sed porttitor</p>
# >> <p>Phasellus <a href="#">tempor example</a> posuere. <span class="foo">Example</span> </p>
# >> </body></html>

基本的にはこれを行います:

  • a_tags = doc.search('a')それらを記憶するためにすべての既存の<a>タグを取得します。
  • docを使用して一貫性を保つために Nokogiri を使用して DOM を HTML に変換し直しto_html、グローバル検索を実行してすべての「サンプル」インスタンスを でラップし<span>、それを新しい DOM に再解析します。/\b (example) \b/ix検索と\1置換に使用していることに注意してください。キャプチャを使用している理由とフラグは調査用ですが、「例」または「例」のいずれかを見つけて処理できることに注意してください。
  • <a>ドキュメントをループしてもう一度タグを探し、それぞれを元のバージョンに置き換えます。gsubこれにより、前のステップで破損したものがクリーンアップされます。

それは私が好むよりも少し強引ですが、まっすぐでもあります。タグ内に「example」という単語が含まれていると、これが壊れます。

賢い XPath の専門家の 1 人が、もっと洗練されたものを提案してくれるかもしれません。

于 2013-08-14T14:57:21.973 に答える