nokogiri несколько элементов из XML в массив - PullRequest
1 голос
/ 29 февраля 2012

У меня есть лента новостей XML, из которой я хочу получать истории, а также несколько элементов из каждой истории. исходный xml находится здесь, и это пример каждой истории.

<news:NewsResult>
        <news:Title>Essex Police/Fire</news:Title>
        <news:Url>http://www.gloucestertimes.com/local/x2118804357/Essex-Police-Fire</news:Url>
        <news:Source>Gloucester Daily Times</news:Source>
        <news:Snippet>ESSEX — An attempt to serve a summons to a Piper Lane resident was thwarted at 2:25 p.m. Monday when police discovered that the person no longer lives at that address. Alarms were set off in error on Belcher Street at 3:12 p.m. Monday, on Main Street at ...</news:Snippet>

Пока у меня есть такой код:

def xml2Var(xmlin)
  #Parse received XML with Nokogiri
  doc = Nokogiri::XML(xmlin)

  #Remove  namespaces  
  doc.remove_namespaces!

  #print dat ish?  
# p p doc

#extract values.
  title = doc.xpath("//Title")
  snippet = doc.xpath("//Snippet")
  url = doc.xpath("//Url")
  source = doc.xpath("//Source")

Я хочупоместите эти значения в массив для каждой истории.Затем добавьте каждую историю в массив историй, чтобы я мог отобразить ее в своем приложении Rails.Я вроде как сумел это сделать, но потом не смог отобразить каждую историю и атрибуты каждой истории.Я думаю, что я использую Xpath неправильно?

Ответы [ 2 ]

4 голосов
/ 01 марта 2012

Чтобы поместить истории в массивы, вы должны сделать что-то вроде:

doc.css("NewsResult").map{|nr| [nr.at('Title'),nr.at('Snippet'),nr.at('Url'),nr.at('Source')].map(&:text)}
1 голос
/ 01 марта 2012

При наличии четырех массивов значений, вы можете чередовать их следующим образом:

titles   = %w[t1 t2 t3 t4]
snippets = %w[n1 n2 n3 n4]
urls     = %w[u1 u2 u3 u4]
sources  = %w[s1 s2 s3 s4]

pp titles.zip(snippets,urls,sources)
#=> [["t1", "n1", "u1", "s1"],
#=>  ["t2", "n2", "u2", "s2"],
#=>  ["t3", "n3", "u3", "s3"],
#=>  ["t4", "n4", "u4", "s4"]]

Однако это может быть опасно.Если в каждом массиве не совпадает одно и то же число (например, если в одном массиве отсутствует источник), они будут неправильно связаны:

titles   = %w[t1 t2 t3 t4]
snippets = %w[n1 n2 n3 n4]
urls     = %w[u1 u2 u3 u4]
sources  = %w[s1    s3 s4]

pp titles.zip(snippets,urls,sources)
#=> [["t1", "n1", "u1", "s1"],
#=>  ["t2", "n2", "u2", "s3"],
#=>  ["t3", "n3", "u3", "s4"],
#=>  ["t4", "n4", "u4", nil]]

Лучше делать то, что @pguardiario предлагает: найти каждый новостной результат, а затем сопоставить его с компонентами.Написано более кратко:

parts = %w[Title Snippet Url Source]
all = doc.css("NewsResult").map{ |nr| parts.map{ |part| nr.at(part).text } }

Это даст вам массив из четырехзначных массивов, где [0] - это текст заголовка, [1] - это фрагмент, и так далее:

all.each do |title,snippet,url,source|
  puts "Title: #{title} @ #{url} came from #{source}"
end

Если вам нужна более удобная конструкция, я бы лично создал Hash, чтобы я не обращался к значениям по магическому индексу:

results = doc.css("NewsResult").map do |result|
  Hash[ parts.map{ |part| [part.downcase.to_sym, result.at(part).text] } ]
end

#…later…
results.each do |result|
  puts "Title: #{result[:title]} @ #{result[:url]} came from #{result[:source]}"
end
...