使用 Nokogiri,如何将 html 转换为有关块元素的文本(确保它们导致换行)
Using Nokogiri, how to convert html to text respecting block elements (ensuring they result in line breaks)
Nokogiri #content
方法不会将块元素转换成段落,例如:
fragment = 'hell<span>o</span><p>world<p>I am Josh</p></p>'
Nokogiri::HTML(fragment).content
=> "helloworldI am Josh"
我希望输出:
=> "hello\n\nworld\n\nI am Josh"
如何将 html 转换为文本以确保块元素导致换行并且 inline elements 被替换为没有 space。
这是我的解决方案:
fragment = 'hell<span>o</span><p>world<p>I am Josh</p></p>'
HtmlToText.process(fragment)
=> "hello\n\nworld\n\nI am Josh"
我遍历 nokogiri 树,边走边构建文本字符串,将文本包装在 "\n\n"
中用于块元素,而 ""
用于内联元素。然后 gsub
清理最后的 \n
个字符。它很笨拙,但有效。
require 'nokogiri'
class HtmlToText
class << self
def process html
nokogiri = Nokogiri::HTML(html)
text = ''
nokogiri.traverse do |el|
if el.class == Nokogiri::XML::Element
sep = inline_element?(el) ? "" : "\n"
if el.children.length <= 0
text += "#{sep}"
else
text = "#{sep}#{sep}#{text}#{sep}#{sep}"
end
elsif el.class == Nokogiri::XML::Text
text += el.text
end
end
text.gsub(/\n{3,}/, "\n\n").gsub(/(\A\n+)|(\n+\z)/, "")
end
private
def inline_element? el
el && el.try(:name) && inline_elements.include?(el.name)
end
def inline_elements
%w(
a abbr acronym b bdo big br button cite code dfn em i img input
kbd label map object q samp script select small span strong sub
sup textarea time tt var
)
end
end
end
您可以使用 #before
和 #after
添加换行符:
doc.search('p,div,br').each{ |e| e.after "\n" }
Nokogiri #content
方法不会将块元素转换成段落,例如:
fragment = 'hell<span>o</span><p>world<p>I am Josh</p></p>'
Nokogiri::HTML(fragment).content
=> "helloworldI am Josh"
我希望输出:
=> "hello\n\nworld\n\nI am Josh"
如何将 html 转换为文本以确保块元素导致换行并且 inline elements 被替换为没有 space。
这是我的解决方案:
fragment = 'hell<span>o</span><p>world<p>I am Josh</p></p>'
HtmlToText.process(fragment)
=> "hello\n\nworld\n\nI am Josh"
我遍历 nokogiri 树,边走边构建文本字符串,将文本包装在 "\n\n"
中用于块元素,而 ""
用于内联元素。然后 gsub
清理最后的 \n
个字符。它很笨拙,但有效。
require 'nokogiri'
class HtmlToText
class << self
def process html
nokogiri = Nokogiri::HTML(html)
text = ''
nokogiri.traverse do |el|
if el.class == Nokogiri::XML::Element
sep = inline_element?(el) ? "" : "\n"
if el.children.length <= 0
text += "#{sep}"
else
text = "#{sep}#{sep}#{text}#{sep}#{sep}"
end
elsif el.class == Nokogiri::XML::Text
text += el.text
end
end
text.gsub(/\n{3,}/, "\n\n").gsub(/(\A\n+)|(\n+\z)/, "")
end
private
def inline_element? el
el && el.try(:name) && inline_elements.include?(el.name)
end
def inline_elements
%w(
a abbr acronym b bdo big br button cite code dfn em i img input
kbd label map object q samp script select small span strong sub
sup textarea time tt var
)
end
end
end
您可以使用 #before
和 #after
添加换行符:
doc.search('p,div,br').each{ |e| e.after "\n" }