2011-01-24 4 views
1

Я пытаюсь разобрать файл XML из Itunes с помощью nokogiri и рельсов 3.Проблема получения XML значение атрибута узла с nokogiri

Вот мой код:

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

Спасибо заранее,

Harris

+0

Nevermind, я понял это. Мне нужно было искать документ, используя ('// feed/entry'), а не просто ('// entry'). – lightyrs

+0

Ваш вопрос заставил меня найти ошибку в моей установке nokogiri, танки. :-) – andrea

+0

Это, возможно, не было вашей проблемой. – Phrogz

ответ

4

Хотя вы заявили, что ваш код работает снова, позвольте мне отметить некоторые недостатки в вашем коде:

  1. Вы находитесь попросив Nokogiri проанализировать XML-канал XML как HTML. Вместо этого вы должны использовать Nokogiri::XML(...); не большая проблема, а не причина этой проблемы.

  2. Вы используете return внутри каждого из них. В коде, который вы указали, это обычно вызывает LocalJumpError: unexpected return. Очевидно, что вы используете этот код внутри метода (который вы нам не показали). Использование return внутри блока не выходит из блока, а приводит к возврату метода включения. Что касается того, что вы, вероятно, захотите, то читайте дальше:

  3. Вы создаете локальную переменную url, но вы ее не используете.

  4. Я предполагаю, что вы пытались найти только url из каждого фида. Однако, используя XPath //[@href], вы действительно делали поиск каждого элемента в документе, который имеет атрибут href="...". Вы повторно находите этот полный набор элементов для каждого entry в документе. (За исключением того, что из-за заявления return вы рано уходили.) И затем, запросив text этого элемента, вы ничего не получите.

  5. Что касается фактической ошибки, которую вы получали, вы пытались получить доступ к podcast.url, но элементы Nokogiri не имеют метода url.

Учитывая схему корм из URL вы поставляемые, вот несколько способов, чтобы получить массив атрибутов href="..." каждого entry/link в документе, в порядке возрастания простоты и предпочтение:

Near-Директ Перевод

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 

Просить только атрибут непосредственно

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 

Использование только XPath, чтобы получить то, что мы хотели в первую очередь

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

Использование Ruby 1.9 синтаксис для сокращения карте позвонить

# Map the result of the XPath by calling `to_s` on each 
itunes_top_300.xpath('//entry/link/@href').map(&:to_s) 
+0

Этот ответ действительно помог мне изучить рубин. Спасибо @Phrogz. – lightyrs

Смежные вопросы