Swift - Как читать координаты из файла gpx

поэтому в моем другом вопрос, который я задал, я узнал, что могу легко создавать файлы gpx, но теперь мне нужно отобразить содержимое файла gpx как MKPolygon. Раньше я создал список со всеми координатами в файле plist, это было легко прочитать, так как я мог просто создать NSDictionary и прочитать его оттуда и найти местоположение, используя ключи, которые предоставляет plist, однако это не так. Кажется, это легко работает в файле gpx.

Я создал этот небольшой фрагмент кода, чтобы прочитать все содержимое файла gpx:

if fileManager.fileExistsAtPath(filePath) {
            let dataBuffer = NSData(contentsOfFile: filePath)
            let dataString = NSString(data: dataBuffer!, encoding: NSUTF8StringEncoding)
            print (dataString)
        }

Итак, теперь у меня есть весь текст в строке, но мне все это не нужно:

<?xml version="1.0" encoding="UTF-8"?>
    <trk>
        <name>test</name>
        <desc>Length: 1.339 km (0.832 mi)</desc>
        <trkseg>
            <trkpt lat="-39.2505337" lon="-71.8418312"></trkpt>
            <trkpt lat="-39.2507414" lon="-71.8420136"></trkpt>
        </trkseg>
    </trk>
</gpx>

Мне просто нужны широта и долгота между тегами <trkpt>, чтобы я мог преобразовать их в местоположения и оттуда преобразовать в MKPolygon.

Любая помощь будет принята с благодарностью, так как я ничего не нашел в Google о том, как читать файлы gpx с помощью swift.

Заранее спасибо - Хорхе


person J.Paravicini    schedule 21.07.2016    source источник


Ответы (2)


Хорошо, я смог прочитать файл gpx со следующим кодом:

import Foundation
import MapKit

//NSXMLParserDelegate needed for parsing the gpx files and NSObject is needed by NSXMLParserDelegate
class TrackDrawer: NSObject, NSXMLParserDelegate {
    //All filenames will be checked and if found and if it's a gpx file it will generate a polygon
    var fileNames: [String]! = [String]()

    init(fileNames: [String]) {
        self.fileNames = fileNames
    }

    //Needs to be a global variable due to the parser function which can't return a value
    private var boundaries = [CLLocationCoordinate2D]()

    //Create a polygon for each string there is in fileNames
    func getPolygons() -> [MKPolygon]? {
        //The list that will be returned
        var polyList: [MKPolygon] = [MKPolygon]()

        for fileName in fileNames! {
            //Reset the list so it won't have the points from the previous polygon
            boundaries = [CLLocationCoordinate2D]()

            //Convert the fileName to a computer readable filepath
            let filePath = getFilePath(fileName)

            if filePath == nil {
                print ("File \"\(fileName).gpx\" does not exist in the project. Please make sure you imported the file and dont have any spelling errors")
                continue
            }

            //Setup the parser and initialize it with the filepath's data
            let data = NSData(contentsOfFile: filePath!)
            let parser = NSXMLParser(data: data!)
            parser.delegate = self

            //Parse the data, here the file will be read
            let success = parser.parse()

            //Log an error if the parsing failed
            if !success {
                print ("Failed to parse the following file: \(fileName).gpx")
            }
            //Create the polygon with the points generated from the parsing process
            polyList.append(MKPolygon(coordinates: &boundaries, count: boundaries.count))

        }
        return polyList
    }

    func getFilePath(fileName: String) -> String? {
        //Generate a computer readable path
        return NSBundle.mainBundle().pathForResource(fileName, ofType: "gpx")
    }

    func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
        //Only check for the lines that have a <trkpt> or <wpt> tag. The other lines don't have coordinates and thus don't interest us
        if elementName == "trkpt" || elementName == "wpt" {
            //Create a World map coordinate from the file
            let lat = attributeDict["lat"]!
            let lon = attributeDict["lon"]!

            boundaries.append(CLLocationCoordinate2DMake(CLLocationDegrees(lat)!, CLLocationDegrees(lon)!))
        }
    }
}

Я надеюсь, что это поможет кому-то

person J.Paravicini    schedule 22.07.2016

Быстрый путь

import Foundation
import CoreLocation

class Parser {
    private let coordinateParser = CoordinatesParser()

    func parseCoordinates(fromGpxFile filePath: String) -> [CLLocationCoordinate2D]? {
        guard let data = FileManager.default.contents(atPath: filePath) else { return nil }
    
        coordinateParser.prepare()
    
        let parser = XMLParser(data: data)
        parser.delegate = coordinateParser

        let success = parser.parse()
    
        guard success else { return nil }
        return coordinateParser.coordinates
    }
}

class CoordinatesParser: NSObject, XMLParserDelegate  {
    private(set) var coordinates = [CLLocationCoordinate2D]()

    func prepare() {
        coordinates = [CLLocationCoordinate2D]()
    }

    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
        guard elementName == "trkpt" || elementName == "wpt" else { return }
        guard let latString = attributeDict["lat"], let lonString = attributeDict["lon"] else { return }
        guard let lat = Double(latString), let lon = Double(lonString) else { return }
        guard let latDegrees = CLLocationDegrees(exactly: lat), let lonDegrees = CLLocationDegrees(exactly: lon) else { return }

        coordinates.append(CLLocationCoordinate2D(latitude: latDegrees, longitude: lonDegrees))
    }
}
person Wujo    schedule 15.12.2020