georust / gpx

Rust read/write support for GPS Exchange Format (GPX)
https://crates.io/crates/gpx
MIT License
102 stars 46 forks source link

allow parsing of arbitrary third-party extensions #8

Open brendanashworth opened 6 years ago

brendanashworth commented 6 years ago

The GPX schema allows for some tags to include arbitrary XML data in the form of the extensions tag:

<...>
Allow any elements from a namespace other than this schema's namespace (lax validation). [0..*]
</...>

Currently rust-gpx has no functionality that allows this data to be parsed or stored in the resulting Gpx instance. This issue is a tracking issue for this feature.

zudov commented 6 years ago

As a first step, I think it'll make most sense to implement lax validation and just ignore the <extensions> tag with all children. I was going to suggest to make read take some setting struct with an option lax (or strict), but now when I think of it, there's shouldn't be much need for that "strict" mode that fails when it encounters <extensions>, so it would be OK to simply ignore it unconditionally.

I'll put a PR for that. Then I'll work a bit with my tracks to get a better grasp of Rust and rust-gpx while we can think about a good way to support third-party extensions. I assume that we want to make it in such a way that support for various extensions can be implemented without modifying rust-gpx (and e.g. passed as parameter, or implicitly via some trait).

brendanashworth commented 6 years ago

@zudov ignoring <extensions> by default sounds like a good first step to me.

One of the struggles we might face is with xml-rs, perhaps there's another library more cut out for the problem. Or, even, we could just pass back the data as some sort of callback or something and let the API consumer write their own decoding program.

w-flo commented 2 years ago

It seems like the first step is now implemented, i.e. skipping any <extensions> elements at various nesting levels, including the <trkpt> and <trk> levels. However, gpx files created/edited in QMapShack (and possibly QLandkarteGT) have an <extensions> element as a direct child node of the <gpx> root element. That leads to an InvalidChildElement("extensions", "gpx") error. So unless this violates the GPX standard in some way (or maybe even then), it might be a good idea to skip the element on that nesting level, too?

JarekToro commented 2 years ago

Wouldn't the best route be to use the extra schemas provided at root to parse the extensions.

From The Docs: You can add extend GPX by adding your own elements from another schema here.

Given the example below with Garmin Extensions

Getting this xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"

And using the xsi:schemaLocation= map.

You then query this file. http://www8.garmin.com/xmlschemas/GpxExtensionsv3.xsd

Which contains the schema for the extentions that start with gpxx <extensions><gpxx:TrackExtension><gpxx:DisplayColor>DarkGray</gpxx:DisplayColor></gpxx:TrackExtension>

This seems to be the to spec approach. Though I'm not sure how rust would be able to handle the scenario. And how that would interact with typing

The referenced file.

<?xml version="1.0"?>
<gpx version="1.1"
creator="Viking 1.10 -- http://viking.sf.net/"
xmlns="http://www.topografix.com/GPX/1/1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns:wptx1="http://www.garmin.com/xmlschemas/WaypointExtension/v1" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v2" xmlns:gpxpx="http://www.garmin.com/xmlschemas/PowerExtension/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www8.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/WaypointExtension/v1 http://www8.garmin.com/xmlschemas/WaypointExtensionv1.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v2 http://www.garmin.com/xmlschemas/TrackPointExtensionv2.xsd http://www.garmin.com/xmlschemas/PowerExtensionv1.xsd">
<wpt lat="40.71488" lon="-74.011422">
  <name>001</name>
</wpt>
<trk>
  <name>Trace</name>
  <extensions><gpxx:TrackExtension><gpxx:DisplayColor>DarkGray</gpxx:DisplayColor></gpxx:TrackExtension></extensions>
  <trkseg>
  <trkpt lat="40.71631157206666" lon="-74.01103529632569">
  </trkpt>
  <trkpt lat="40.7154983764096" lon="-74.00927576721192">
  </trkpt>
  <trkpt lat="40.71435988580241" lon="-74.01021990478516">
  </trkpt>
  <trkpt lat="40.7139370129041" lon="-74.00888952911377">
  </trkpt>
  <trkpt lat="40.71149730912246" lon="-74.01047739685059">
  </trkpt>
  </trkseg>
</trk>
<rte>
  <name>Route</name>
  <extensions><gpxx:TrackExtension><gpxx:DisplayColor>Red</gpxx:DisplayColor></gpxx:TrackExtension></extensions>
</rte>
</gpx>
w-flo commented 2 years ago

Personally, I think the previous pull request for this (simply hand the raw XML string over to the application) was not the worst approach.

Basically, if the gpx crate wants to do anything more than "allow the application to access the raw XML string" for extensions, it would have to expose functionality from the XML parsing crate used by this crate. So just pass on any XML parsing events inside those tags to the user application. But maybe some users don't really like event-based XML parsing and would still prefer to access the raw XML, so they can feed it into their preferred XML DOM parser even though that's a bit less efficient and needs a bit more dependencies / blows up the binary size a bit.

Maybe some common extensions can be supported and parsed by the gpx crate itself. However, I don't think there's a general solution for this issue that supports all extensions and is "better" than a generic XML parser. And allowing to access the raw extension XML might very well be part of an "ideal" solution?

brendanashworth commented 2 years ago

@w-flo yeah, it's been 4 years and nobody's built it so the old pull request was probably better to merge than not. Do you want to rebase and reopen the last PR?

JeromeSchmied commented 4 months ago

I've found this repo, which contains very great stuff, eg. gpx exporting with extensions in this file, perhaps even extension parsing.

also, uses this very crate (gpx)