使用nokogiri获取XML节点属性值时出现问题

时间:2011-01-24 00:25:02

标签: xml itunes nokogiri

我正在尝试使用nokogiri和rails 3解析iTunes中的XML文件。

这是我的代码:

itunes_top_300 = Nokogiri.HTML(open("http://itunes.apple.com/us/rss/toppodcasts/limit=300/xml"))

itunes_top_300.search('//entry').each do |podcast|
  url = podcast.xpath("//[@href]]").text
  return podcast.url
end

当我加载调用此方法的视图时,我得到:

未定义的方法`url'

这是我要解析的xml:

http://itunes.apple.com/us/rss/toppodcasts/limit=300/xml

提前致谢,

哈里斯

1 个答案:

答案 0 :(得分:4)

虽然您已经声明您的代码再次运行,但我要指出代码中的一些缺陷:

  1. 您要求Nokogiri将XML RSS提要解析为HTML。你应该使用Nokogiri::XML( ... );没什么大不了的,也不是造成这个问题的原因。

  2. 您在每个人中使用return。在您显示的代码中,通常会导致LocalJumpError: unexpected return。显然,您在方法中使用此代码(您尚未向我们展示)。在块内使用return不会退出块,而是使封闭方法返回。至于你可能想要的东西,请继续阅读:

  3. 您正在创建一个本地url变量,但您没有使用它。

  4. 我猜你要做的就是从每个Feed中找到url。但是,通过使用XPath //[@href],您实际上正在查找文档中具有href="..."属性的每个元素。您正在为文档中的每个entry重新找到这整套元素。 (除了由于return声明,你提前退出。)然后,通过询问元素的text,你将一无所获。

  5. 至于您遇到的实际错误,您试图访问podcast.url,但Nokogiri元素没有url方法。

  6. 根据您提供的URL提要的架构,以下是以简单和优先级递增的顺序获取文档中每个href="..."的{​​{1}}属性数组的不同方法:

    近直接翻译

    entry/link

    摆脱局部变量

    urls = []
    itunes_top_300.search('//entry').each do |podcast|
      # Find the first element below the current one that has an href attribute
      # and then get the value of that attribute
      url = podcast.at_xpath(".//[@href]")['href']
    
      # Add this url to the array
      urls << url
    end
    
    # As the last statement in your method, return urls (without word 'return')
    urls
    

    使用地图清理

    urls = []
    itunes_top_300.search('//entry').each do |podcast|
      # It's pretty clear what we're doing, so no need to name the value
      # before we add it to the array
      urls << podcast.at_xpath(".//[@href]")['href']
    end
    urls
    

    直接询问属性

    # Run through the array and convert each element to the return value
    # of the block
    itunes_top_300.search('//entry').map do |podcast|
      podcast.at_xpath(".//[@href]")['href']
    end
    
    # If the above is the last statement of the method, the method will return the
    # result of the map as the return value of the method
    

    首先只使用XPath获取我们想要的内容

    itunes_top_300.search('//entry').map do |podcast|
      # Instead of getting the element, get the attribute itself
      # Use `to_s` or `value` to get the text of the attribute node.
      podcast.at_xpath(".//[@href]/@href").to_s
    end
    

    使用Ruby 1.9语法缩短地图调用

    # Take an array of attribute nodes and get their values
    itunes_top_300.xpath('//entry/link/@href').map{ |attr| attr.to_s }