首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Hpricot XML文本搜索

Hpricot XML文本搜索
EN

Stack Overflow用户
提问于 2011-02-12 05:33:09
回答 2查看 551关注 0票数 1

Hpricot + Ruby XML解析和逻辑选择。

目标:查找作者Bob所写的所有标题。

我的XML文件:

代码语言:javascript
复制
<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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-02-12 08:18:50

XPath背后的一个想法是,它允许我们像导航磁盘目录一样导航DOM:

代码语言:javascript
复制
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的所有书籍,然后查找一个级别,找到title标签”。

我添加了一本由"Bob“写的额外的书来测试获取所有的匹配项。

要获取包含Bob的一本书的项目,只需上移一级:

代码语言:javascript
复制
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中应该是相同的:

代码语言:javascript
复制
(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访问器,为了维护和清晰起见,我建议使用这些格式。

票数 2
EN

Stack Overflow用户

发布于 2011-02-12 06:01:35

如果您没有在Hpricot上设置,这里有一种在Nokogiri中使用XPath来完成此操作的方法

代码语言:javascript
复制
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也工作得很好,可读性更好,而且速度可能会更快:

代码语言:javascript
复制
bobs_titles = doc.xpath("//author[text()='Bob']/../title")
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4974304

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档