diff --git a/gpx-rs/engine/data/self_closing_points.gpx b/gpx-rs/engine/data/self_closing_points.gpx
new file mode 100644
index 000000000..2b119cd85
--- /dev/null
+++ b/gpx-rs/engine/data/self_closing_points.gpx
@@ -0,0 +1,26 @@
+
+
+
+ self closing points
+ Points without children are self-closing elements.
+
+ 2.0
+
+
+
+
+ with children
+
+
+ track
+
+
+ 12.5
+
+
+
+
+
+
+
diff --git a/gpx-rs/engine/src/core/io/parse.rs b/gpx-rs/engine/src/core/io/parse.rs
index 2e0871ece..4650c3738 100644
--- a/gpx-rs/engine/src/core/io/parse.rs
+++ b/gpx-rs/engine/src/core/io/parse.rs
@@ -114,6 +114,30 @@ pub fn parse(data: &[u8], categories: &mut TrackpointCategories) -> Result stack.push(GPXElement::Width),
_ => (),
},
+ // Self-closing points (``), which have no children
+ Ok(Event::Empty(e)) => match e.name().as_ref() {
+ "trkpt" => {
+ if let Some(GPXElement::Segment(trkseg)) = stack.last_mut() {
+ trkpt_chunk.trkpt.push(Trackpoint {
+ coordinates: parse_coordinates(e.attributes()),
+ ..Default::default()
+ });
+ if trkpt_chunk.is_full() {
+ trkseg.push(std::mem::take(&mut trkpt_chunk));
+ }
+ }
+ }
+ "wpt" => {
+ wpt_chunk.wpt.push(Waypoint {
+ coordinates: parse_coordinates(e.attributes()),
+ ..Default::default()
+ });
+ if wpt_chunk.is_full() {
+ gpx.wpt.push(Rc::new(std::mem::take(&mut wpt_chunk)));
+ }
+ }
+ _ => (),
+ },
Ok(Event::End(e)) => match e.name().as_ref() {
"gpx" => {
if !wpt_chunk.wpt.is_empty() {
@@ -363,6 +387,30 @@ mod tests {
.unwrap()
}
+ #[test]
+ fn test_parse_self_closing_points() {
+ let gpx = parse_data("self_closing_points");
+
+ assert_eq!(gpx.info.name, "self closing points");
+ let wpt: Vec<_> = gpx.wpt.iter().flat_map(|chunk| &chunk.wpt).collect();
+ assert_eq!(wpt.len(), 3);
+ assert_eq!(wpt[0].coordinates.lat, 50.0);
+ assert_eq!(wpt[0].name, None);
+ assert_eq!(wpt[1].name.as_deref(), Some("with children"));
+ assert_eq!(wpt[2].coordinates.lng, 4.2);
+
+ assert_eq!(gpx.trk.len(), 1);
+ let trk = &gpx.trk[0];
+ assert_eq!(trk.trkseg.len(), 2);
+ let seg = &trk.trkseg[0];
+ assert_eq!(seg.len(), 3);
+ assert_eq!(seg[0].coordinates.lat, 50.0);
+ assert_eq!(seg[0].ele, 0.0);
+ assert_eq!(seg[1].ele, 12.5);
+ assert_eq!(seg[2].coordinates.lng, 4.02);
+ assert_eq!(trk.trkseg[1].len(), 1);
+ }
+
#[test]
fn test_parse_simple() {
let gpx = parse_data("simple");