当我从HTML或XML刮取几个相关的节点以提取文本时,所有文本都合并为一个长字符串,从而无法恢复单个文本字符串。
例如:
require 'nokogiri' doc = Nokogiri::HTML(<<EOT) <html> <body> <p>foo</p> <p>bar</p> <p>baz</p> </body> </html> EOT doc.search('p').text # => "foobarbaz"
但是我想要的是:
["foo", "bar", "baz"]
抓取XML时也会发生相同的情况:
doc = Nokogiri::XML(<<EOT) <root> <block> <entries>foo</entries> <entries>bar</entries> <entries>baz</entries> </block> </root> EOT doc.search('entries').text # => "foobarbaz"
为什么会发生这种情况,我该如何避免呢?
这是一个容易解决的问题,其原因是没有阅读有关text在NodeSet和Node(或Element)上使用时的行为的文档。
text
该节点集文档表示text将:
获取所有包含的Node对象的内部文本
我们看到的是:
doc = Nokogiri::HTML(<<EOT) <html> <body> <p>foo</p> <p>bar</p> <p>baz</p> </body> </html> EOT doc.search('p').text # => "foobarbaz"
因为:
doc.search('p').class # => Nokogiri::XML::NodeSet
相反,我们要获取每个Node并提取其文本:
doc.search('p').first.class # => Nokogiri::XML::Element doc.search('p').first.text # => "foo"
可以使用map:
map
doc.search('p').map { |node| node.text } # => ["foo", "bar", "baz"]
Ruby允许我们使用以下代码更简洁地编写代码:
doc.search('p').map(&:text) # => ["foo", "bar", "baz"]
无论我们使用的是HTML还是XML,同样的事情也适用,因为HTML是XML的一种更为宽松的版本。
节点具有几种获取其嵌入文本的别名方法。从文档中:
#content ⇒ Object
也称为:text,inner_text
inner_text
返回此节点的内容。