<TrainingCenterDatabase xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd">
<Activities>
<Activity Sport="Running">
<Id>2011-04-29T15:29:42Z</Id>
<Lap StartTime="2011-04-29T15:29:42Z">
<TriggerMethod>Manual</TriggerMethod>
<Track>
<Trackpoint>
<AltitudeMeters>298.6267090</AltitudeMeters>
<Position>
<LatitudeDegrees>52.4864997</LatitudeDegrees>
<LongitudeDegrees>13.3531452</LongitudeDegrees>
</Position>
</Trackpoint>
</Track>
</Lap>
<Lap StartTime="2011-04-29T15:29:42Z">
<TriggerMethod>Manual</TriggerMethod>
<Track>
<Trackpoint>
<AltitudeMeters>498.6267090</AltitudeMeters>
<Position>
<LatitudeDegrees>52.4864997</LatitudeDegrees>
<LongitudeDegrees>13.3531452</LongitudeDegrees>
</Position>
</Trackpoint>
</Track>
</Lap>
</Activity>
</Activities>
</TrainingCenterDatabase>
doc = Nokogiri::XML(xml)
node_values = doc.xpath('//xmlns:Track', 'xmlns' => 'http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2').map do |i|
{'AltitudeMeters' => i.xpath('//xmlns:AltitudeMeters').text}
end
nl.debug(node_values)
我的结果总是有两个条目:
[{"AltitudeMeters"=>"298.6267090498.6267090"},
{"AltitudeMeters"=>"298.6267090498.6267090"}]
我想要这样的东西:
[{"AltitudeMeters"=>"298.6267090"},
{"AltitudeMeters"=>"498.6267090"}]
问题可能出在xmlns上。但我不知道解决办法。
doc = Nokogiri::XML(xml)
node_values = doc.xpath('//xmlns:Track//xmlns:AltitudeMeters', 'xmlns' => 'http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2').map do |i|
{'AltitudeMeters' => i.text}
end
p node_values
# => [{"AltitudeMeters"=>"298.6267090"}, {"AltitudeMeters"=>"498.6267090"}]
问题出在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}]