Ваша проблема с вашим селектором XPath. Когда вы пишете:
i.xpath('//xmlns:AltitudeMeters')
вы начинаете с корня документа и находите каждый элемент <AltitudeMeters>
на любом уровне, а не только дочерние элементы дорожки, которую вы просматриваете в данный момент. Минимальное изменение, которое вы можете сделать, это изменить ваш селектор XPath на .//xmlns:AltitudeMeters
(обратите внимание на начальный период):
doc = Nokogiri::XML(xml)
tracks = doc.xpath( '//xmlns:Track' ) # You don't need to specify the namespace
node_values = tracks.map do |track|
{ 'AltitudeMeters' => track.xpath('.//xmlns:AltitudeMeters').text }
end
p node_values
#=> {"AltitudeMeters"=>"298.6267090"}, {"AltitudeMeters"=>"498.6267090"}]
Кроме того, если на дорожку есть только один Trackpoint
, я бы использовал at_xpath
, что возвращает первый соответствующий элемент. Действительно, если ваша схема не является изменчивой, я бы также указал, где именно найти высоту, которую я хотел:
node_values = tracks.map do |track|
{ 'AltitudeMeters' =>
track.at_xpath('./xmlns:Trackpoint/xmlns:AltitudeMeters').text }
end
Наконец, поскольку вы, кажется, работаете с документом с одним пространством имен, обратите внимание, что вы можете попросить Nokogiri отбросить все пространства имен, чтобы сделать вашу жизнь проще:
doc = Nokogiri::XML(xml)
doc.remove_namespaces!
node_values = doc.xpath( '//Track/Trackpoint' ).map do |track|
{
'Altitude' => track.at_xpath('./AltitudeMeters').text.to_f,
'Latitude' => track.at_xpath('./Position/LatitudeDegrees').text.to_f,
'Longitude' => track.at_xpath('./Position/LongitudeDegrees').text.to_f
}
end
require 'pp'
pp node_values
#=> [{"Altitude"=>298.626709, "Latitude"=>52.4864997, "Longitude"=>13.3531452},
#=> {"Altitude"=>498.626709, "Latitude"=>52.4864997, "Longitude"=>13.3531452}]