Replace Hpricot with Nokogiri

master
Guillaume Dott 2013-06-16 01:20:28 +02:00
parent b1d18e8261
commit 917c437f94
11 changed files with 91 additions and 143 deletions

View File

@ -18,5 +18,5 @@ Gem::Specification.new do |s|
s.homepage = "http://dougfales.github.com/gpx/"
s.rubyforge_project = "gpx"
s.add_dependency 'hpricot'
s.add_dependency 'nokogiri'
end

View File

@ -20,12 +20,12 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
$:.unshift(File.dirname(__FILE__))
require 'rubygems'
require 'hpricot'
require 'date'
require 'time'
require 'csv'
require 'nokogiri'
require 'gpx/version'
require 'gpx/gpx'
require 'gpx/gpx_file'
require 'gpx/bounds'

View File

@ -43,15 +43,6 @@ module GPX
(min_lon + distance)
end
def to_xml
bnd = XML::Node.new('bounds')
bnd['minlat'] = min_lat.to_s
bnd['minlon'] = min_lon.to_s
bnd['maxlat'] = max_lat.to_s
bnd['maxlon'] = max_lon.to_s
bnd
end
# Returns true if the pt is within these bounds.
def contains?(pt)
(pt.lat >= min_lat and pt.lat <= max_lat and pt.lon >= min_lon and pt.lon <= max_lon)

View File

@ -34,7 +34,7 @@ module GPX
# attributes to this method.
def instantiate_with_text_elements(parent, text_elements)
text_elements.each do |el|
child_xpath = "//#{el}"
child_xpath = "#{el}"
unless parent.at(child_xpath).nil?
val = parent.at(child_xpath).inner_text
self.send("#{el}=", val)

View File

@ -22,7 +22,7 @@
#++
module GPX
class GPXFile < Base
attr_accessor :tracks, :routes, :waypoints, :bounds, :lowest_point, :highest_point, :duration, :ns, :version, :time, :name
attr_accessor :tracks, :routes, :waypoints, :bounds, :lowest_point, :highest_point, :duration, :ns, :time, :name
# This initializer can be used to create a new GPXFile from an existing
@ -47,24 +47,14 @@ module GPX
if(opts[:gpx_file] or opts[:gpx_data])
if opts[:gpx_file]
gpx_file = opts[:gpx_file]
#case gpx_file
#when String
# gpx_file = File.open(gpx_file)
#end
gpx_file = gpx_file.name if gpx_file.is_a?(File)
@xml = Hpricot(File.open(gpx_file))
gpx_file = File.open(gpx_file) unless gpx_file.is_a?(File)
@xml = Nokogiri::XML(gpx_file)
else
@xml = Hpricot(opts[:gpx_data])
@xml = Nokogiri::XML(opts[:gpx_data])
end
# set XML namespace for XML find
#if @xml.root.namespaces.namespace
# @ns = 'gpx:' + @xml.root.namespaces.namespace.href
#else
# @ns = 'gpx:http://www.topografix.com/GPX/1/1' # default to GPX 1.1
#end
reset_meta_data
bounds_element = (@xml.at("//metadata/bounds") rescue nil)
bounds_element = (@xml.at("metadata/bounds") 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})
@ -74,18 +64,18 @@ module GPX
get_bounds = true
end
@time = Time.parse(@xml.at("//metadata/time").inner_text) rescue nil
@name = @xml.at("//metadata/name").inner_text rescue nil
@time = Time.parse(@xml.at("metadata/time").inner_text) rescue nil
@name = @xml.at("metadata/name").inner_text rescue nil
@tracks = []
@xml.search("//trk").each do |trk|
@xml.search("trk").each do |trk|
trk = Track.new(:element => trk, :gpx_file => self)
update_meta_data(trk, get_bounds)
@tracks << trk
end
@waypoints = []
@xml.search("//wpt").each { |wpt| @waypoints << Waypoint.new(:element => wpt, :gpx_file => self) }
@xml.search("wpt").each { |wpt| @waypoints << Waypoint.new(:element => wpt, :gpx_file => self) }
@routes = []
@xml.search("//rte").each { |rte| @routes << Route.new(:element => rte, :gpx_file => self) }
@xml.search("rte").each { |rte| @routes << Route.new(:element => rte, :gpx_file => self) }
@tracks.delete_if { |t| t.empty? }
calculate_duration
@ -205,52 +195,83 @@ module GPX
@time = Time.now if(@time.nil? or update_time)
@name ||= File.basename(filename)
doc = generate_xml_doc
doc.save(filename, :indent => true)
File.open(filename, 'w') { |f| f.write(doc.to_xml) }
end
def to_s(update_time = true)
@time = Time.now if(@time.nil? or update_time)
doc = generate_xml_doc
doc.to_s
doc.to_xml
end
def inspect
"<#{self.class.name}:...>"
end
private
def generate_xml_doc
doc = Document.new
doc.root = Node.new('gpx')
gpx_elem = doc.root
gpx_elem['xsi'] = "http://www.w3.org/2001/XMLSchema-instance"
@version = '1.1' if (@version.nil? || !(['1.0', '1.1'].include?(@version))) # default to version 1.1 of the schema (only version 1.0 and 1.1 of the schema exist)
version_dir = @version.gsub('.','/')
gpx_elem['xmlns'] = @ns || "http://www.topografix.com/GPX/#{version_dir}"
gpx_elem['version'] = "#{@version}"
gpx_elem['creator'] = "GPX RubyGem #{GPX::VERSION} Copyright 2006-2009 Doug Fales -- http://gpx.rubyforge.org/"
gpx_elem['xsi:schemaLocation'] = "http://www.topografix.com/GPX/#{version_dir} http://www.topografix.com/GPX/#{version_dir}/gpx.xsd"
version = '1.1'
version_dir = version.gsub('.','/')
# setup the metadata elements
name_elem = Node.new('name')
name_elem << @name
time_elem = Node.new('time')
time_elem << @time.xmlschema
doc = Nokogiri::XML::Builder.new do |xml|
xml.gpx(
'xsi' => "http://www.w3.org/2001/XMLSchema-instance",
'version' => version.to_s,
'creator' => "GPX RubyGem #{GPX::VERSION}",
'xsi:schemaLocation' => "http://www.topografix.com/GPX/#{version_dir} http://www.topografix.com/GPX/#{version_dir}/gpx.xsd") \
{
xml.metadata {
xml.name @name
xml.time @time.xmlschema
xml.bound(
minlat: bounds.min_lat,
minlon: bounds.min_lon,
maxlat: bounds.max_lat,
maxlon: bounds.max_lon,
)
}
# version 1.0 of the schema doesn't support the metadata element, so push them straight to the root 'gpx' element
if (@version == '1.0') then
gpx_elem << name_elem
gpx_elem << time_elem
gpx_elem << bounds.to_xml
else
meta_data_elem = Node.new('metadata')
meta_data_elem << name_elem
meta_data_elem << time_elem
meta_data_elem << bounds.to_xml
gpx_elem << meta_data_elem
end
tracks.each do |t|
xml.trk {
xml.name t.name
tracks.each { |t| gpx_elem << t.to_xml } unless tracks.nil?
waypoints.each { |w| gpx_elem << w.to_xml } unless waypoints.nil?
routes.each { |r| gpx_elem << r.to_xml } unless routes.nil?
t.segments.each do |seg|
xml.trkseg {
seg.points.each do |p|
xml.trkpt(lat: p.lat, lon: p.lon) {
xml.time p.time.xmlschema unless p.time.nil?
xml.ele p.elevation unless p.elevation.nil?
}
end
}
end
}
end unless tracks.nil?
return doc
waypoints.each do |w|
xml.wpt(lat: w.lat, lon: w.lon) {
Waypoint::SUB_ELEMENTS.each do |sub_elem|
xml.send(sub_elem, w.send(sub_elem)) if w.respond_to?(sub_elem) && !w.send(sub_elem).nil?
end
}
end unless waypoints.nil?
routes.each do |r|
xml.rte {
xml.name r.name
r.points.each do |p|
xml.rtept(lat: p.lat, lon: p.lon) {
xml.time p.time.xmlschema unless p.time.nil?
xml.ele p.elevation unless p.elevation.nil?
}
end
}
end unless routes.nil?
}
end
return doc
end
# Calculates and sets the duration attribute by subtracting the time on

View File

@ -20,6 +20,9 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++
require 'csv'
module GPX
# This class will parse the lat/lon and time data from a Magellan track log,

View File

@ -87,22 +87,5 @@ module GPX
@lonr = (longitude * D_TO_R)
@lon = longitude
end
# Convert this point to a XML::Node.
def to_xml(elem_name = 'trkpt')
pt = Node.new(elem_name)
pt['lat'] = lat.to_s
pt['lon'] = lon.to_s
unless time.nil?
time_elem = Node.new('time')
time_elem << time.xmlschema
pt << time_elem
end
elev = Node.new('ele')
elev << elevation
pt << elev
pt
end
end
end

View File

@ -34,9 +34,9 @@ module GPX
if(opts[:gpx_file] and opts[:element])
rte_element = opts[:element]
@gpx_file = opts[:gpx_file]
@name = rte_element.at("//name").inner_text
@name = rte_element.at("name").inner_text
@points = []
rte_element.search("//rtept").each do |point|
rte_element.search("rtept").each do |point|
@points << Point.new(:element => point, :gpx_file => @gpx_file)
end
else
@ -55,16 +55,5 @@ module GPX
def delete_area(area)
points.delete_if{ |pt| area.contains? pt }
end
# Convert this Route to a XML::Node.
def to_xml
rte = Node.new('rte')
name_elem = Node.new('name')
name_elem << name
rte << name_elem
points.each { |rte_pt| rte << rte_pt.to_xml('rtept') }
rte
end
end
end

View File

@ -46,8 +46,8 @@ module GPX
if(opts[:element])
segment_element = opts[:element]
last_pt = nil
if segment_element.is_a?(Hpricot::Elem)
segment_element.search("//trkpt").each do |trkpt|
if segment_element.is_a?(Nokogiri::XML::Node)
segment_element.search("trkpt").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)
@ -132,13 +132,6 @@ module GPX
(points.nil? or (points.size == 0))
end
# Converts this Segment to a XML::Node object.
def to_xml
seg = Node.new('trkseg')
points.each { |pt| seg << pt.to_xml }
seg
end
# Prints out a nice summary of this Segment.
def to_s
result = "Track Segment\n"

View File

@ -41,8 +41,8 @@ module GPX
reset_meta_data
if(opts[:element])
trk_element = opts[:element]
@name = (trk_element.at("//name").inner_text rescue "")
trk_element.search("//trkseg").each do |seg_element|
@name = (trk_element.at("name").inner_text rescue "")
trk_element.search("trkseg").each do |seg_element|
seg = Segment.new(:element => seg_element, :track => self, :gpx_file => @gpx_file)
update_meta_data(seg)
@segments << seg
@ -100,18 +100,6 @@ module GPX
(points.nil? or points.size.zero?)
end
# Creates a new XML::Node from the contents of this instance.
def to_xml
trk= Node.new('trk')
name_elem = Node.new('name')
name_elem << name
trk << name_elem
segments.each do |seg|
trk << seg.to_xml
end
trk
end
# Prints out a friendly summary of this track (sans points). Useful for
# debugging and sanity checks.

View File

@ -27,7 +27,7 @@ module GPX
# not seen much use yet, since WalkingBoss does not use waypoints right now.
class Waypoint < Point
SUB_ELEMENTS = %w{ magvar geoidheight name cmt desc src link sym type fix sat hdop vdop pdop ageofdgpsdata dgpsid extensions }
SUB_ELEMENTS = %w{ magvar geoidheight name cmt desc src link sym type fix sat hdop vdop pdop ageofdgpsdata dgpsid extensions ele}
attr_reader :gpx_file
SUB_ELEMENTS.each { |sub_el| attr_accessor sub_el.to_sym }
@ -72,25 +72,5 @@ module GPX
end
result
end
# Converts a waypoint to a XML::Node.
def to_xml(elem_name = 'wpt')
wpt = Node.new(elem_name)
wpt['lat'] = lat.to_s
wpt['lon'] = lon.to_s
SUB_ELEMENTS.each do |sub_element_name|
if(self.respond_to?(sub_element_name) and (!self.send(sub_element_name).nil?))
sub_elem_node = Node.new(sub_element_name)
sub_elem_node << self.send(sub_element_name)
wpt << sub_elem_node
end
end
unless(self.elevation.nil?)
ele_node = Node.new('ele')
ele_node << self.elevation
wpt << ele_node
end
wpt
end
end
end