User:GranD/API Perl example
Jump to navigation
Jump to search
#!/usr/bin/perl
use strict;
binmode(STDIN, ':utf8');
binmode(STDERR, ':utf8');
use LWP::UserAgent;
use HTTP::Request;
use XML::Parser;
use utf8;
use POSIX qw/strftime/;
my $cs_create_url = "http://api.openstreetmap.org/api/0.6/changeset/create";
sub cs_upload_url {
my $id = shift;
return "http://api.openstreetmap.org/api/0.6/changeset/$id/upload";
}
sub cs_close_url {
my $id = shift;
return "http://api.openstreetmap.org/api/0.6/changeset/$id/close";
}
sub el_get_url {
my $type = shift;
my $id = shift;
return "http://api.openstreetmap.org/api/0.6/$type/$id";
}
my $login = "login";
my $passwd = "password";
my $ua = LWP::UserAgent->new;
$ua->credentials ('api.openstreetmap.org:80', 'Web Password', $login => $passwd);
my ($req, $res, $changeset_id);
my %node, my %tags, my @nd;
$req = HTTP::Request->new(PUT=>$cs_create_url);
$req->content_type('text/xml');
$req->content("<osm><changeset><tag k='comment' v='some comment here'/></changeset></osm>");
print STDERR "Opening changeset...";
$res = $ua->request($req) || die("Cannot open changeset, test your connection");
$changeset_id = $res->content;
print STDERR " succesful, id=$changeset_id\n";
#creating XML Parser
my $parser = new XML::Parser(ProtocolEncoding => 'UTF-8', Handlers => {Start => \&xml_start});
#parsing input data
my $timestamp = strftime ("%Y-%m-%dT%H:%M:%S.0+04:00", gmtime);
my $text = "<osmChange version=\"0.3\" generator=\"Perl\">\n <modify>\n";
while(<>) {
chomp;
next if /^\s*#/; #ignore comments
@nd = ();
if (/(node|way)\t(\d+)\t(.+)/) {
my ($ctype, $cid, $cname) = ($1, $2, $3);
print STDERR "Requesting data for $ctype $cid...\n";
$req = HTTP::Request->new(GET=>el_get_url($ctype, $cid));
$res = $ua->request($req);
my $xml = $res->content;
#print STDERR $xml."\n";
%node = %tags = ();
$parser->parse($xml);
$tags{'name:ru'} = $cname;
$node{'timestamp'} = $timestamp;
if ($ctype eq 'node') {
$text .= " <node id=\"$node{id}\" timestamp=\"$node{timestamp}\" lat=\"$node{lat}\" lon=\"$node{lon}\" changeset=\"$changeset_id\" version=\"$node{version}\">\n";
} elsif ($ctype eq 'way') {
$text .= " <way id=\"$node{id}\" timestamp=\"$node{timestamp}\" changeset=\"$changeset_id\" version=\"$node{version}\">\n";
}
for my $k(sort keys %tags) {
$text .= " <tag k=\"$k\" v=\"$tags{$k}\"/>\n";
}
for my $r(@nd) {
$text .= " <nd ref=\"$r\"/>\n";
}
$text .= " </$ctype>\n";
} else {
print STDERR "String <$_> is not valid\n";
}
}
$text .= " </modify>\n</osmChange>";
if (utf8::is_utf8($text)) {
utf8::encode($text); #important!
}
$req = HTTP::Request->new(POST=>cs_upload_url($changeset_id));
$req->content_type('text/xml');
$req->content($text);
print STDERR "Uploading...\n";
$res = $ua->request($req);
print STDERR $res->content;
$req = HTTP::Request->new(PUT=>cs_close_url($changeset_id));
print STDERR "Closing changeset... ";
$res = $ua->request($req);
print STDERR $res->content."\n";
#subs
sub xml_start {
my ($elem, $tag, %attr) = @_;
if ($tag eq 'node' || $tag eq 'way') {
for my $k (keys %attr) {
$node{$k} = $attr{$k};
}
} elsif ($tag eq 'tag') {
$tags{$attr{'k'}} = xml_escape($attr{'v'});
} elsif ($tag eq 'nd') {
push @nd, $attr{'ref'};
}
}
sub xml_escape {
my $s = shift;
$s =~ s/"/"/g;
$s =~ s/'/'/g;
$s =~ s/</</g;
$s =~ s/>/>/g;
return $s;
}