Html 包装非';t在带有Nokogiri的锚标签内

Html 包装非';t在带有Nokogiri的锚标签内,html,ruby,parsing,nokogiri,Html,Ruby,Parsing,Nokogiri,我有一些HTML: <p>Lorem ipsum example laoreet. <a href="#">example</a>Cum porttitor</p> <p>Phasellus <a href="#">gravida tempor example</a> magna</p> 我可以使用以下命令将标记环绕另一个标记的文本内容: doc.xpath('//p//text()') - doc

我有一些HTML:

<p>Lorem ipsum example laoreet. <a href="#">example</a>Cum porttitor</p>
<p>Phasellus <a href="#">gravida tempor example</a> magna</p>
我可以使用以下命令将标记环绕另一个标记的文本内容:

doc.xpath('//p//text()') - doc.xpath('//p//a/text()')
doc.search('div.some-class text()').wrap('<span class="something"></span>')
doc.search('div.some-class text()').wrap(“”)
但是如何在该内容中的文本周围包装标记?

也可以使用
text()
Xpath选择器来匹配这样的文本:

但我认为这样做行不通:

doc.search("div.some-class text()='example'").wrap('<span class="something"></span>')
doc.search(“div.some-class text()='example')。换行(“”)
以下是我的做法:

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>
需要“nokogiri”
doc=Nokogiri::HTML(>
# >> 
# >> 
#>Lorem ipsum示例位于amet.Sed porttitor

#>Phasellus posuere.示例

# >>
基本上是这样的:

  • a_tags=doc.search('a')
    获取所有现有的
    标记以记住它们
  • 我使用Nokogiri将
    doc
    DOM转换回HTML,以确保一致性,使用
    转换为\u HTML
    ,然后执行全局搜索和替换,将所有“示例”实例包装到
    中,然后将其重新分析为新的DOM。注意,我使用的是
    /\b(示例)\b/ix
    用于搜索和替换中的
    \1
    。为什么我使用捕获和标记供您研究,但您应该注意,它让我查找并处理“示例”或“示例”
  • 再次在文档中循环查找
    标记,并将每个标记替换为其原始版本。这将清除在上一步中被
    gsub
    损坏的所有标记
这比我喜欢的更暴力一点,但它也在前面。如果在标签中找到“示例”这个词,这将被打破


也许有一个聪明的XPath专家会加入一些更优雅的东西。

您可能需要在Ruby中操作有问题的文本节点,然后在文档中使用Nokogiri将为您解析的新文本

doc.xpath('//p/genderant或self::node()[name()!=“a”]/text()[contains(,“example”)]')。每个|
n、 替换(n.content.gsub(/(示例)/,'\1'))
结束
在本例中,我使用了比您稍复杂的XPath查询。它选择任何
p
元素的所有文本节点后代,除非它们是
a
元素的后代,我认为这正是您想要的。(我不知道这是否对您更有利,请尝试并查看。)


回答您问题的位是块的内容。这里,我获取每个文本节点的字符串内容,并使用中的新
span
元素创建一个新的标记字符串。然后,我使用
replace
将此片段放在文档中原始文本节点的位置。Nokogiri将解析此字符串并添加创建的节点来代替原始文本节点。这在许多方面与gsub类似,但更具针对性,因为它只涉及使用
gsub
并重新解析有问题的文本节点。

以下是我最后的做法:

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;", ">")
doc=Nokogiri::HTML(HTML)
#选择不在锚定标记内的段落内容
elements=doc.xpath('//p//text()')-doc.xpath('//p//a/text()'))
#在元素上交互,用锚定标记包裹“短语”
元素。每个do |元素|
element.content=element.content.gsub(短语“”)
结束
#修正Nokogiri无论如何都想逃离尖括号的欲望
doc.xpath('//body')[0].inner_html.gsub(“,”)

这并没有回答我的问题。为了帮助那些帮助你的人,将你的HTML减少到显示问题或作为示例输入所需的最小值。在保持可读性的同时,尽量将它放在尽可能小的空间中。在这种情况下,HTML很长,因为有一堆不必要的Lorem文本,所以它的滚动“恩,没必要那样做。”泰曼说得对。完成了。
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>
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;", ">")