Updates courtesy of Gaku Ueda:

* Adding support for GPX 1.0 as well as 1.1 (since libxml namespace parsing
   was hard-coded to 1.1. previously).
 * Adding a GPX 1.0 unit test file.
 * Miscellaneous updates to make it work with Ruby 1.8.6.
master
Doug Fales 2007-11-30 06:26:26 +00:00
parent 022c7c6813
commit 5aa64f2c3a
8 changed files with 55 additions and 18 deletions

View File

@ -28,7 +28,6 @@ module GPX
class Base
include XML
NS = 'gpx:http://www.topografix.com/GPX/1/1'
# This initializer can take an XML::Node and scrape out any text
# elements with the names given in the "text_elements" array. Each
# element found underneath "parent" with a name in "text_elements" causes

View File

@ -22,7 +22,7 @@
#++
module GPX
class GPXFile < Base
attr_reader :tracks, :routes, :waypoints, :bounds, :lowest_point, :highest_point, :distance, :duration, :average_speed
attr_reader :tracks, :routes, :waypoints, :bounds, :lowest_point, :highest_point, :distance, :duration, :average_speed, :ns
# This initializer can be used to create a new GPXFile from an existing
@ -50,9 +50,16 @@ module GPX
#end
gpx_file = gpx_file.name if gpx_file.is_a?(File)
reset_meta_data
@xml = Document.file(gpx_file)
@xml = XML::Document.file(gpx_file)
bounds_element = (@xml.find("//gpx:gpx/gpx:metadata/gpx:bounds", NS).to_a.first rescue nil)
# set XML namespace for XML find
if @xml.root.namespace_node
@ns = 'gpx:' + @xml.root.namespace_node.href
else
@ns = 'gpx:http://www.topografix.com/GPX/1/1' # default to GPX 1.1
end
bounds_element = (@xml.find("//gpx:gpx/gpx:metadata/gpx:bounds", @ns).to_a.first rescue nil)
if bounds_element
@bounds.min_lat = get_bounds_attr_value(bounds_element, %w{ min_lat minlat minLat })
@bounds.min_lon = get_bounds_attr_value(bounds_element, %w{ min_lon minlon minLon})
@ -63,15 +70,15 @@ module GPX
end
@tracks = []
@xml.find("//gpx:gpx/gpx:trk", NS).each do |trk|
@xml.find("//gpx:gpx/gpx:trk", @ns).each do |trk|
trk = Track.new(:element => trk, :gpx_file => self)
update_meta_data(trk, get_bounds)
@tracks << trk
end
@waypoints = []
@xml.find("//gpx:gpx/gpx:wpt", NS).each { |wpt| @waypoints << Waypoint.new(:element => wpt, :gpx_file => self) }
@xml.find("//gpx:gpx/gpx:wpt", @ns).each { |wpt| @waypoints << Waypoint.new(:element => wpt, :gpx_file => self) }
@routes = []
@xml.find("//gpx:gpx/gpx:rte", NS).each { |rte| @routes << Route.new(:element => rte, :gpx_file => self) }
@xml.find("//gpx:gpx/gpx:rte", @ns).each { |rte| @routes << Route.new(:element => rte, :gpx_file => self) }
@tracks.delete_if { |t| t.empty? }

View File

@ -32,13 +32,14 @@ module GPX
# addition, you can pass an XML element to this initializer, and the
# relevant info will be parsed out.
def initialize(opts = {:lat => 0.0, :lon => 0.0, :elevation => 0.0, :time => Time.now } )
@gpx_file = opts[:gpx_file]
if (opts[:element])
elem = opts[:element]
@lat, @lon = elem["lat"].to_f, elem["lon"].to_f
@latr, @lonr = (D_TO_R * @lat), (D_TO_R * @lon)
#'-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
@time = (Time.xmlschema(elem.find("gpx:time", NS).first.content) rescue nil)
@elevation = elem.find("gpx:ele", NS).first.content.to_f unless elem.find("gpx:ele", NS).empty?
@time = (Time.xmlschema(elem.find("gpx:time", @gpx_file.ns).first.content) rescue nil)
@elevation = elem.find("gpx:ele", @gpx_file.ns).first.content.to_f unless elem.find("gpx:ele", @gpx_file.ns).empty?
else
@lat = opts[:lat]
@lon = opts[:lon]

View File

@ -33,9 +33,9 @@ module GPX
def initialize(opts = {})
rte_element = opts[:element]
@gpx_file = opts[:gpx_file]
@name = rte_element.find("child::gpx:name", NS).first.content
@name = rte_element.find("child::gpx:name", @ns).first.content
@points = []
rte_element.find("child::gpx:rtept", NS).each do |point|
rte_element.find("child::gpx:rtept", @ns).each do |point|
@points << Point.new(:element => point)
end

View File

@ -34,6 +34,7 @@ module GPX
# If a XML::Node object is passed-in, this will initialize a new
# Segment based on its contents. Otherwise, a blank Segment is created.
def initialize(opts = {})
@gpx_file = opts[:gpx_file]
@track = opts[:track]
@points = []
@earliest_point = nil
@ -46,8 +47,8 @@ module GPX
segment_element = opts[:element]
last_pt = nil
if segment_element.is_a?(XML::Node)
segment_element.find("child::gpx:trkpt", NS).each do |trkpt|
pt = TrackPoint.new(:element => trkpt, :segment => self)
segment_element.find("child::gpx:trkpt", @gpx_file.ns).each do |trkpt|
pt = TrackPoint.new(:element => trkpt, :segment => self, :gpx_file => @gpx_file)
unless pt.time.nil?
@earliest_point = pt if(@earliest_point.nil? or pt.time < @earliest_point.time)
@latest_point = pt if(@latest_point.nil? or pt.time > @latest_point.time)

View File

@ -41,9 +41,9 @@ module GPX
reset_meta_data
if(opts[:element])
trk_element = opts[:element]
@name = (trk_element.find("child::gpx:name", NS).first.content rescue "")
trk_element.find("child::gpx:trkseg", NS).each do |seg_element|
seg = Segment.new(:element => seg_element, :track => self)
@name = (trk_element.find("child::gpx:name", @gpx_file.ns).first.content rescue "")
trk_element.find("child::gpx:trkseg", @gpx_file.ns).each do |seg_element|
seg = Segment.new(:element => seg_element, :track => self, :gpx_file => @gpx_file)
update_meta_data(seg)
@segments << seg
@points.concat(seg.points) unless seg.nil?

View File

@ -0,0 +1,12 @@
require 'test/unit'
require File.dirname(__FILE__) + '/../lib/gpx'
class TestGPX10 < Test::Unit::TestCase
GPX_FILE = File.join(File.dirname(__FILE__), "gpx_files/gpx10.gpx")
def test_read
# make sure we can read a GPX 1.0 file
@gpx_file = GPX::GPXFile.new(:gpx_file => GPX_FILE)
end
end

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.0"
creator="GPSBabel - http://www.gpsbabel.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.topografix.com/GPX/1/0"
xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
<trk>
<name>ACTIVE LOG #74</name>
<number>82</number>
<trkseg>
<trkpt lat="37.378388923" lon="-122.063654875">
<ele>35.706055</ele>
<time>2007-11-23T23:49:43Z</time>
</trkpt>
</trkseg>
</trk>
</gpx>