Crates.io | osm-xml |
lib.rs | osm-xml |
version | 0.6.2 |
source | src |
created_at | 2016-07-22 15:04:12.248472 |
updated_at | 2018-02-03 12:04:14.698315 |
description | OSM xml parser for Rust |
homepage | https://github.com/orva/osm-xml |
repository | |
max_upload_size | |
id | 5750 |
size | 61,418 |
Simple osm xml v0.6 parser.
Structure for the parsed data follows closely how OSM documents are formed: we have top level OSM struct containing bounds, nodes array, ways array and relations array. Each parsed element follows closely their corresponding osm-wiki entry.
References to the other elements in the document are left unresolved in parsed form. There is API to resolve individual references to their corresponding elements, but whole document cannot be made connected.
Tags for the element are stored in .tags
field as array of Tag { key: String, val: String }
.
Below is simple example program which digs out some statistics from given osm-document. This includes parsing document, finding and using all the different kind of elements and resolving references (both resolvable and unresolvable).
extern crate osm_xml as osm;
use std::fs::File;
fn main() {
let f = File::open("/path/to/map.osm").unwrap();
let doc = osm::OSM::parse(f).unwrap();
let rel_info = relation_reference_statistics(&doc);
let way_info = way_reference_statistics(&doc);
let poly_count = doc.ways.values().fold(0, |acc, way| {
if way.is_polygon() {
return acc + 1
}
acc
});
println!("Node count {}", doc.nodes.len());
println!("Way count {}", doc.ways.len());
println!("Polygon count {}", poly_count);
println!("Relation count {}", doc.relations.len());
println!("Tag count {}", tag_count(&doc));
println!("Way reference count: {}, invalid references: {}", way_info.0, way_info.1);
println!("Relation reference count: {}, resolved: {}, unresolved: {}", rel_info.0, rel_info.1, rel_info.2);
}
fn relation_reference_statistics(doc: &osm::OSM) -> (usize, usize, usize) {
doc.relations.values()
.flat_map(|relation| relation.members.iter())
.fold((0, 0, 0), |acc, member| {
let el_ref = match *member {
osm::Member::Node(ref el_ref, _) => el_ref,
osm::Member::Way(ref el_ref, _) => el_ref,
osm::Member::Relation(ref el_ref, _) => el_ref,
};
match doc.resolve_reference(&el_ref) {
osm::Reference::Unresolved => (acc.0 + 1, acc.1, acc.2 + 1),
osm::Reference::Node(_) |
osm::Reference::Way(_) |
osm::Reference::Relation(_) => (acc.0 + 1, acc.1 + 1, acc.2)
}
})
}
fn way_reference_statistics(doc: &osm::OSM) -> (usize, usize) {
doc.ways.values()
.flat_map(|way| way.nodes.iter())
.fold((0, 0), |acc, node| {
match doc.resolve_reference(&node) {
osm::Reference::Node(_) => (acc.0 + 1, acc.1),
osm::Reference::Unresolved |
osm::Reference::Way(_) |
osm::Reference::Relation(_) => (acc.0, acc.1 + 1)
}
})
}
fn tag_count(doc: &osm::OSM) -> usize {
let node_tag_count = doc.nodes.values()
.map(|node| node.tags.len())
.fold(0, |acc, c| acc + c);
let way_tag_count = doc.ways.values()
.map(|way| way.tags.len())
.fold(0, |acc, c| acc + c);
let relation_tag_count = doc.relations.values()
.map(|relation| relation.tags.len())
.fold(0, |acc, c| acc + c);
node_tag_count + way_tag_count + relation_tag_count
}
combining OSM-structs (something simple, make it easier to update existing elements inside map bounds)
writing out OSM documents
common element attribute parsing (visible, author, changeset, etc)
customizing parsing behaviour (short circuit on errors, optional fields, etc)
nicer error reporting: position in the osm-document of the offending element
tag "database": would make finding elements with tags faster / saves memory on parsed structure as tags are just references to actual strings
2018-02-03
2017-04-25
Read
instead of File
2016-07-28
2016-07-22
Initial release
osm-xml is licensed under MIT-license. See more in LICENSE.