Skip to content

Instantly share code, notes, and snippets.

@eeeeeta
Last active November 26, 2015 07:20
Show Gist options
  • Save eeeeeta/f2ae3545fde094d04f32 to your computer and use it in GitHub Desktop.
Save eeeeeta/f2ae3545fde094d04f32 to your computer and use it in GitHub Desktop.
first bit of rust code - parses GPX trackpoints. probably quite buggy :P
extern crate xml;
extern crate chrono;
use std::fs::File;
use std::io::BufReader;
use std::vec::Vec;
use chrono::*;
use xml::reader::{EventReader, XmlEvent};
fn indent(size: usize) -> String {
const INDENT: &'static str = " ";
(0..size).map(|_| INDENT)
.fold(String::with_capacity(size*INDENT.len()), |r, s| r + s)
}
struct GPXPoint {
lat: f64,
lon: f64,
elev: Option<f64>,
time: Option<DateTime<FixedOffset>>
}
fn main() {
let file = File::open("file.xml").unwrap();
let file = BufReader::new(file);
let parser = EventReader::new(file);
let mut depth = 0;
let mut pts: Vec<GPXPoint> = Vec::new();
let mut elem: Option<GPXPoint> = None;
let mut curname: String = "blarg.".to_string();
for e in parser {
match e {
Ok(XmlEvent::StartElement { name, attributes, .. }) => {
println!("{} START {}", indent(depth), name);
curname = name.local_name;
if curname.contains("trkpt") {
println!("trkpt found");
let mut pt = GPXPoint { lat: 0.0f64, lon: 0.0f64, elev: None, time: None };
for attr in attributes {
println!("{} ATTR: {} = {}", indent(depth + 1), attr.name, attr.value);
match attr.name.local_name.as_ref() {
"lat" => {
pt.lat = attr.value.parse().unwrap();
println!("lat: {}", pt.lat);
}
"lon" => {
pt.lon = attr.value.parse().unwrap();
println!("lon: {}", pt.lon);
}
_ => {
println!("warn: unknown attr {}", attr.name);
}
}
}
elem = Some(pt);
}
depth += 1;
}
Ok(XmlEvent::EndElement { name }) => {
depth -= 1;
if name.local_name.contains("trkpt") {
match elem {
Some(pt) => {
println!("pushing trkpt: {}, {}, {:?}, {:?}", pt.lat, pt.lon, pt.elev, pt.time);
pts.push(pt);
},
None => {}
}
elem = None;
}
println!("{}-{}", indent(depth), name);
}
Ok(XmlEvent::CData(string)) => {
println!("{} CDATA: {}", indent(depth), string);
}
Ok(XmlEvent::Characters(string)) => {
println!("{} {} CHARS: {}", indent(depth), curname, string);
match elem {
Some(ref mut pt) => {
match curname.as_ref() {
"ele" => {
println!("ele: {}", string);
pt.elev = Some(string.parse().unwrap());
},
"time" => {
println!("time: {}", string);
let result = DateTime::parse_from_rfc3339(&string);
match result {
Ok(time) => {
println!("time parsed\n");
pt.time = Some(time);
}
Err(e) => {
panic!("error parsing time: {}", e);
}
}
},
_ => {}
}
}
None => {}
}
}
Err(e) => {
println!("Error: {}", e);
break;
}
_ => {}
}
}
println!("====\nPARSE COMPLETE\n====\n\n");
for pt in &pts {
println!("Trackpoint: [{}, {}] at elev {:?} at time {:?}", pt.lat, pt.lon, pt.elev, pt.time);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment