gpx.js (4349B)
1 import {decode as utf8_decode} from 'utf8'; 2 import {xmlGetNodeText} from './xmlUtils'; 3 import stripBom from '~/lib/stripBom'; 4 5 function parseGpx(txt, name, preferNameFromFile) { 6 var error; 7 8 function getSegmentPoints(segment_element) { 9 var points_elements = segment_element.getElementsByTagName('trkpt'); 10 var points = []; 11 for (var i = 0; i < points_elements.length; i++) { 12 var point_element = points_elements[i]; 13 var lat = parseFloat(point_element.getAttribute('lat')); 14 var lng = parseFloat(point_element.getAttribute('lon')); 15 if (isNaN(lat) || isNaN(lng)) { 16 error = 'CORRUPT'; 17 break; 18 } 19 points.push({lat: lat, lng: lng}); 20 } 21 return points; 22 } 23 24 function getTrackSegments(xml) { 25 var segments = []; 26 var segments_elements = xml.getElementsByTagName('trkseg'); 27 for (var i = 0; i < segments_elements.length; i++) { 28 var segment_points = getSegmentPoints(segments_elements[i]); 29 if (segment_points.length) { 30 segments.push(segment_points); 31 } 32 } 33 return segments; 34 } 35 36 function getRoutePoints(rte_element) { 37 var points_elements = rte_element.getElementsByTagName('rtept'); 38 var points = []; 39 for (var i = 0; i < points_elements.length; i++) { 40 var point_element = points_elements[i]; 41 var lat = parseFloat(point_element.getAttribute('lat')); 42 var lng = parseFloat(point_element.getAttribute('lon')); 43 if (isNaN(lat) || isNaN(lng)) { 44 error = 'CORRUPT'; 45 break; 46 } 47 points.push({lat: lat, lng: lng}); 48 } 49 return points; 50 } 51 52 function getRoutes(xml) { 53 var routes = []; 54 var rte_elements = xml.getElementsByTagName('rte'); 55 for (var i = 0; i < rte_elements.length; i++) { 56 var rte_points = getRoutePoints(rte_elements[i]); 57 if (rte_points.length) { 58 routes.push(rte_points); 59 } 60 } 61 return routes; 62 } 63 64 function getWaypoints(xml) { 65 var waypoint_elements = xml.getElementsByTagName('wpt'); 66 var waypoints = []; 67 for (var i = 0; i < waypoint_elements.length; i++) { 68 var waypoint_element = waypoint_elements[i]; 69 var waypoint = {}; 70 waypoint.lat = parseFloat(waypoint_element.getAttribute('lat')); 71 waypoint.lng = parseFloat(waypoint_element.getAttribute('lon')); 72 if (isNaN(waypoint.lat) || isNaN(waypoint.lng)) { 73 error = 'CORRUPT'; 74 continue; 75 } 76 let wptName = xmlGetNodeText(waypoint_element.getElementsByTagName('name')[0]) || ''; 77 try { 78 wptName = utf8_decode((wptName)); 79 } catch (e) { 80 error = 'CORRUPT'; 81 wptName = '__invalid point name__'; 82 } 83 waypoint.name = wptName; 84 waypoint.symbol_name = xmlGetNodeText(waypoint_element.getElementsByTagName('sym')[0]); 85 waypoints.push(waypoint); 86 } 87 return waypoints; 88 } 89 90 txt = stripBom(txt); 91 // remove namespaces 92 txt = txt.replace(/<([^ >]+):([^ >]+)/ug, '<$1_$2'); 93 let dom; 94 try { 95 dom = (new DOMParser()).parseFromString(txt, "text/xml"); 96 } catch (e) { 97 return null; 98 } 99 if (dom.documentElement.nodeName === 'parsererror') { 100 return null; 101 } 102 if (dom.getElementsByTagName('gpx').length === 0) { 103 return null; 104 } 105 if (preferNameFromFile) { 106 for (let trk of [...dom.getElementsByTagName('trk')]) { 107 let trkName = trk.getElementsByTagName('name')[0]; 108 if (trkName) { 109 try { 110 trkName = utf8_decode(xmlGetNodeText(trkName)); 111 } catch (e) { 112 error = 'CORRUPT'; 113 } 114 if (trkName.length) { 115 name = trkName; 116 break; 117 } 118 } 119 } 120 } 121 return [{ 122 name: name, 123 tracks: getTrackSegments(dom).concat(getRoutes(dom)), 124 points: getWaypoints(dom), 125 error: error 126 }]; 127 } 128 129 export default parseGpx;