Когда в Раменском какой-то добрый леловек из альтруистических побуждений заменил в названиях улиц "ул." на "улица" и сбил всю адресацию, я понял, что это не дело. Название улицы должно быть только в одном экземпляре. Этог можно добиться используя отношения типа
street. Оно пока не утверждено, но в полной мере удовлетворяет тому, что мне нужно. Вот только ни рендереры, ни конвертеры его не поддерживают. Поэтому пришлось написать скриптик, который копирует название из отношения в его участников. Просто выгружаем кусочек с помощью JOSM, скармливаем скрипту:
php street.php current.osm new.osm
И заливаем его обратно.
<?php
$doc = new DOMDocument();
$doc->loadXML(file_get_contents($_SERVER['argv'][1]));
function replaceTag (&$object, $tag, $value) {
global $doc;
$changed = true;
$tags = $object->getElementsByTagName("tag");
$found = false;
foreach ($tags as $otag) {
if ($otag->getAttribute('k') == $tag) {
$found = true;
if ($otag->getAttribute("v") == $value)
$changed = false;
else
$otag->setAttribute("v", $value);
}
}
if (!$found) {
$otag = $doc->createElement('tag');
$object->appendChild($otag);
$otag->setAttribute("k", $tag);
$otag->setAttribute("v", $value);
}
return $changed;
}
$relations = $doc->getElementsByTagName ("relation");
foreach ($relations as $relation) {
$tags = $relation->getElementsByTagName("tag");
$type = false;
$name = false;
foreach ($tags as $tag) {
if ($tag->getAttribute('k') == "type") {
$type = $tag->getAttribute('v');
}
if ($tag->getAttribute('k') == "name") {
$name = $tag->getAttribute('v');
}
}
if ($type != "street" || !$name)
continue 1;
echo "Processing " . $name . "\n";
$members = $relation->getElementsByTagName("member");
foreach ($members as $member) {
$id = $member->getAttribute('ref');
echo "\t " . $member->getAttribute('type') . " $id";
$refs = $doc->getElementsByTagName($member->getAttribute('type'));
foreach ($refs as $ref) {
if ($ref->getAttribute('id') == $id) {
$changed = false;
echo " +";
switch ($member->getAttribute('role')) {
case street:
$changed = replaceTag ($ref, "name", $name);
break;
case house:
$changed = replaceTag ($ref, "addr:street", $name);
break;
}
if ($changed){
$ref->setAttribute("action", "modify");
}
break;
}
}
echo "\n";
}
}
$fp = fopen($_SERVER['argv'][2], 'w');
fwrite($fp, $doc->saveXML());
fclose($fp);