#!/usr/bin/perl
#---------------------------------------------------------------------
#	$Id: osm_csv.pl,v 1.7 2012/01/10 17:21:43 wolf Exp wolf $
#---------------------------------------------------------------------

use strict;
use utf8;

use open ':utf8';

binmode STDIN, ':utf8';
binmode STDOUT, ':utf8';
binmode STDERR, ':utf8';

#---------------------------------------------------------------------
#	Options
#---------------------------------------------------------------------
#	tags={tag,tag,...}
#	ignore={tag,tag,...}
#	noheader=1
#---------------------------------------------------------------------

my %Opt;
while ($ARGV[0] =~ /^-(\w+)(=(.*))?$/) {
	$Opt{$1} = $2 ne '' ? $3 : 1;
	shift (@ARGV);
}

#---------------------------------------------------------------------
#	Taglists
#---------------------------------------------------------------------

my @standardTags= ('id', 'lat', 'lon');
my @baseTags	= split /\s+/, $Opt{'tags'};
my @ignoreTags	= split /\s+/, $Opt{'ignore'};

#---------------------------------------------------------------------
#	Vars
#---------------------------------------------------------------------

my ($id, @ids, %data, %tags);

#---------------------------------------------------------------------
#	Read OSM
#---------------------------------------------------------------------

sub unentity {
	my ($s) = @_;
	$s =~ s#&lt;#<#g;
	$s =~ s#&gt;#>#g;
	$s =~ s#&apos;#'#g;
	$s =~ s#&quot;#"#g;
	$s =~ s#&amp;#&#g;
	return $s;
}

while (<>) {
	if (m#\s*<tag k='([^']+)' v='([^']+)'\s*/># && $id) {
		my $tag = $1;
		my $val = $2;
		next if $tag =~ /&/;
		$data{$id, $tag} = unentity ($val);
		$tags{$tag}++;
		next;
	}
	if (m#\s*<tag k="([^"]+)" v="([^"]+)"\s*/># && $id) {
		my $tag = $1;
		my $val = $2;
		next if $tag =~ /&/;
		$data{$id, $tag} = unentity ($val);
		$tags{$tag}++;
		next;
	}
	if (m#^\s*<node id=['"](\d+)['"] [^<>]*\blat=['"](-?\d+\.?\d*)['"] lon=['"](-?\d+\.?\d*)['"]#) {
		$id = $1;
		push (@ids, $id);
		$data{$id, 'id' } = $id;
		$data{$id, 'lat'} = $2;
		$data{$id, 'lon'} = $3;;
		next;
	}
	if (m#^\s*</node>#) {
		$id = undef;
		next;
	}
}

#---------------------------------------------------------------------
#	ignored tags
#---------------------------------------------------------------------

foreach my $tag (@ignoreTags) {
	delete $tags{$tag};
}

#---------------------------------------------------------------------
#	use baseTags or standard tags
#---------------------------------------------------------------------

my @tags = @baseTags ? @baseTags : @standardTags;
foreach my $tag (@tags) { delete $tags{$tag}; }
my @unknownTags = sort {lc($a) cmp lc($b)} keys %tags;
push (@tags, @unknownTags) unless @baseTags;
warn "\n\nUNKNOWN: ",join(', ',@unknownTags),"\n\n" if @baseTags && @unknownTags;

#---------------------------------------------------------------------
#	CSV header
#---------------------------------------------------------------------

print join ("\t",@tags),"\n" unless $Opt{'noheader'};

#---------------------------------------------------------------------
#	CSV data
#---------------------------------------------------------------------

foreach my $id (sort {$a<=>$b} @ids) {

	my @data;
	foreach my $tag (@tags) { push (@data, $data{$id, $tag}); };
	print join ("\t",@data),"\n";
}

exit 0;

#---------------------------------------------------------------------
#	$Id: osm_csv.pl,v 1.7 2012/01/10 17:21:43 wolf Exp wolf $
#---------------------------------------------------------------------
