[英]Hpricot XML text search
Hpricot + Ruby XML解析和逻辑选择。
目标:查找作者鲍勃撰写的所有标题。
我的XML文件:
<rss>
<channel>
<item>
<title>Book1</title>
<pubDate>march 1 2010</pubDate>
<author>Bob</author>
</item>
<item>
<title>book2</title>
<pubDate>october 4 2009</pubDate>
<author>Bill</author>
</item>
<item>
<title>book3</title>
<pubDate>June 5 2010</pubDate>
<author>Steve</author>
</item>
</channel>
</rss>
#my Hpricot, running this code returns no output, however the search pattern works on its own.
(doc % :rss % :channel / :item).each do |item|
a=item.search("author[text()*='Bob']")
#puts "FOUND" if a.include?"Bob"
puts item.at("title") if a.include?"Bob"
end
如果您没有设置Hpricot,这是使用Nokogiri中的 XPath做到这一点的一种方法:
require 'nokogiri'
doc = Nokogiri::XML( my_rss_string )
bobs_titles = doc.xpath("//title[parent::item/author[text()='Bob']]")
p bobs_titles.map{ |node| node.text }
#=> ["Book1"]
编辑 :@theTinMan的XPath也可以很好地工作,可读性更好,并且可能会更快:
bobs_titles = doc.xpath("//author[text()='Bob']/../title")
XPath背后的想法之一是它允许我们以类似于磁盘目录的方式浏览DOM:
require 'hpricot'
xml = <<EOT
<rss>
<channel>
<item>
<title>Book1</title>
<pubDate>march 1 2010</pubDate>
<author>Bob</author>
</item>
<item>
<title>book2</title>
<pubDate>october 4 2009</pubDate>
<author>Bill</author>
</item>
<item>
<title>book3</title>
<pubDate>June 5 2010</pubDate>
<author>Steve</author>
</item>
<item>
<title>Book4</title>
<pubDate>march 1 2010</pubDate>
<author>Bob</author>
</item>
</channel>
</rss>
EOT
doc = Hpricot(xml)
titles = (doc / '//author[text()="Bob"]/../title' )
titles # => #<Hpricot::Elements[{elem <title> "Book1" </title>}, {elem <title> "Book4" </title>}]>
这意味着:“查找Bob的所有书籍,然后向上一级查找并找到标题标签”。
我添加了“鲍勃”(Bob)编写的另一本书,以测试所有情况的发生。
要获取Bob所藏的书籍,只需将其上移一个级别即可:
items = (doc / '//author[text()="Bob"]/..' )
puts items # => nil
# >> <item>
# >> <title>Book1</title>
# >> <pubdate>march 1 2010</pubdate>
# >> <author>Bob</author>
# >> </item>
# >> <item>
# >> <title>Book4</title>
# >> <pubdate>march 1 2010</pubdate>
# >> <author>Bob</author>
# >> </item>
我还弄清楚了(doc % :rss % :channel / :item)
在做什么。 这等效于嵌套搜索,减去包装括号,并且所有这些在Hpricot-ese中都应该相同:
(doc % :rss % :channel / :item).size # => 4
(((doc % :rss) % :channel) / :item).size # => 4
(doc / '//rss/channel/item').size # => 4
(doc / 'rss channel item').size # => 4
因为通常会以'//rss/channel/item'
形式看到XPath访问器,而'rss channel item'
是CSS访问器,所以我建议使用这些格式进行维护和清晰化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.