假设我有这种标记:
<li> Some text </li>
<li> <strong> Some text </strong> hello</li>
我需要确保在打开的<li>
标记之后和任何封闭的文本内容之前没有空白间隙。与野村一起实现这一目标的最佳方式是什么?
期望结果:
<li>Some text </li>
<li><strong>Some text </strong> hello</li>
删除整个文档中的所有前导/尾随空白:
doc.xpath('//text()').each do |node|
if node.content=~/S/
node.content = node.content.strip
else
node.remove
end
end
但是,请注意,这将把<p>Hello <b>World</b></p>
变成<p>Hello<b>World</b></p>
。您可能需要更精确地指定您想要的内容。
编辑:这里有一个更好的解决方案,可以从元素的第一个子元素的所有文本节点中删除前导空格,并从最后一个子元素的文本节点中移除所有尾随空格:
doc.xpath('//text()[1]').each{ |t| t.content = t.content.lstrip }
doc.xpath('//text()[last()]').each{ |t| t.content = t.content.rstrip }
已投入使用:
html = '<ul>
<li> First text </li>
<li> <strong> Some text </strong> </li>
<li> I am <b> embedded </b> and need <i>some </i> <em>spaces</em>. </li>
</ul>'
require 'nokogiri'
doc = Nokogiri.HTML(html)
doc.xpath('//text()[1]').each{ |t| t.content = t.content.lstrip }
doc.xpath('//text()[last()]').each{ |t| t.content = t.content.rstrip }
puts doc.root
#=> <html><body><ul>
#=> <li>First text</li><li><strong>Some text</strong></li>
#=> <li>I am <b>embedded</b> and need <i>some</i> <em>spaces</em>.</li></ul></body></html>
编辑#2:以下是如何将其从<li>
:前面的文本节点上剥离
doc.xpath('//li/text()[1]').each{ |t| t.content = t.content.lstrip }
您将遍历每个li,删除前导空格,直到找到一些文本:
doc.css('li').each do |li|
li.traverse do |node|
node.content = node.content.gsub(/^s+/,'')
break unless node.content.empty?
end
end
在操作Nokogiri::HTML.fragment
时,xpath("//text()")
似乎不起作用。
以下是我提出的
doc.traverse do |node|
if node.is_a? Nokogiri::XML::Text
node.content = node.content.lstrip if node.previous_element&.description&.block?
node.content = node.content.lstrip if node.previous_element.nil? && node.parent.description&.block?
node.content = node.content.rstrip if node.next_element&.description&.block?
node.content = node.content.rstrip if node.next_element.nil? && node.parent.description&.block?
node.remove if node.content.empty?
end
end
注意:使用Ruby 2.3语法