ちょっとした実験として、エクスポートされたOSMデータセットを XML から Prologに変換したいと思います。
XML から Prolog への特定の汎用コンバーター (例: Pl4Xml ) があることは知っていますが、これらの汎用コンバーターはこの問題を解決する最善の方法ですか? OSM データをPrologで便利な表現に変換するライブラリについて誰かが知っているのではないでしょうか?
ちょっとした実験として、エクスポートされたOSMデータセットを XML から Prologに変換したいと思います。
XML から Prolog への特定の汎用コンバーター (例: Pl4Xml ) があることは知っていますが、これらの汎用コンバーターはこの問題を解決する最善の方法ですか? OSM データをPrologで便利な表現に変換するライブラリについて誰かが知っているのではないでしょうか?
セルジオ、私は最善の方法を知りません。しかし、私は OSM で自分自身の小さな実験を行いました。Pl4XML は使用せず、SWI-Prolog とライブラリ (sgml) のみを使用しました。このような:
tt2(tag, Attrs, _) :-
memberchk(k=Key, Attrs),
\+ tag(Key), assertz(tag(Key)),
fail ; true.
?- dynamic tag/1.
?- new_sgml_parser(Parser, []),
open('UA.osm', read, Stream),
sgml_parse(Parser, [source(Stream), call(begin, tt2)]),
free_sgml_parser(Parser),
close(Stream).
UA.osm は私の XML データです。1000 種類以上のタグ キーがあります。適切に処理する必要があります。tags
最良の方法は、OSM のノード、ウェイ、共通メンバーとの関係に述語を使用し、タグ データをキーと値のペア (または AVL ツリー) の順序付けられたセットとして表すことだと思います。私はUranium Testの開発者なので、 Uraniumは Prolog に最適なオブジェクト モデルを提供してくれると思います (特定の Prolog 実装にロックされていません)。OSM オブジェクトの関係を管理する方法の例を示します。
:- module(node_v, [on_begin/3, on_end/2]).
:- use_module(u(v)).
% helper for callback tag parsing
new_class(xml_tag_v, db_object_v, [closed_by_parser]).
% OSM element
new_class(element_v, xml_tag_v,
[id,
changeset,
visible,
user,
timestamp,
tags]).
% OSM node, way and barrier - children of element
new_class(node_v, element_v, [lat, lon]).
new_class(way_v, element_v, [nodes]).
new_class(barrier_v, element_v, [barrier_type]).
% Example of a tag-based dynamic class
% (see http://wiki.openstreetmap.org/wiki/Barriers)
'element_v?'(Obj, class, barrier_v) :-
obj_field(Obj, tags, Tags),
% if it contains Key:barrier it is a barrier
% (way or node)
memberchk(barrier-_, Tags), !.
% XML parsing callbacks
on_begin(node, Attrs, _) :-
% Construct the node_v object
obj_construct(node_v, [], [], Obj),
foreach(member(Name=Value, Attrs),
obj_field(Obj, weak, Name, Value)),
% Put it into DB 'nodes'
db_recorda(nodes, Obj).
on_begin(tag, Attrs, _) :-
db_recorded(nodes, Obj0), !,
obj_rewrite(Obj0,
[closed_by_parser, tags],
[Is_Closed, Tags0],
[Is_Closed, Tags], Obj),
var(Is_Closed), !, % found unclosed node
memberchk(k=Key, Attrs),
memberchk(v=Value, Attrs),
( var(Tags0) -> Tags1 = [] ; Tags1 = Tags0 ),
Tags = [Key - Value|Tags1], % add new tag
db_recorda(nodes, _, Obj, _, replaced). % db update
on_end(node, _) :-
% close the node parsing
db_recorded(nodes, Obj0), !,
obj_rewrite(Obj0,
[closed_by_parser, tags],
[_, Tags0],
[true, Tags], Obj),
( var(Tags0)
-> Tags = []
; sort(Tags0, Tags) % if your expectation for a number of tags is big
% try use library(assoc) (AVL trees)
),
db_put_object(nodes, _, Obj, _, replaced).
new_class/3 はクラスを定義します - これは通常のプロローグ用語で、(追加の述語の助けを借りて) 値への名前付きアクセスの可能性と、継承、オブジェクト データベースなどの他の多くのものがあります。モジュールは 3 つの主要な OSM エンティティを定義します - node_v
、way_v
およびrelation_v
(_v はオブジェクトのサフィックスです) の子としてelement_v
. それぞれelement_v
にtags
フィールドが含まれています。
barrier_v
タグ キー (または値) に基づいて OSM クラスを認識する方法の例です。この例では、特別な述語「element_v?」/3 がオブジェクトのクラスを計算します。barrier_v は、node_v または way_v のいずれかの子にすることができます (この例には示されていません)。
モジュールの最後の部分は、XML (コールバック) パーサーです。~1.7G ファイルでテストしましたが、うまく動作します (SWI-Prolog)。
ノード - 標準の Prolog データベースに基づくオブジェクト DB です (外部の PostgreSQL も将来のバージョンで使用できます)。
1 つの解析結果の例は次のとおりです。
?- db_recorded(nodes, N), obj_pretty_print(N), !.
N = node_v(70, '6176525', true, nodes, 32, '10980421', '46.4718061', '30.7308961',
[highway-traffic_signals], '2010-10-25T19:17:07Z', 'Buccaneer', _G391)
node_v (
changeset : 6176525
closed_by_parser : true
db_key : nodes
db_ref : 32
id : 10980421
lat : 46.4718061
lon : 30.7308961
tags : [highway-traffic_signals]
timestamp : 2010-10-25T19:17:07Z
user : Buccaneer
)
また、Uranium は、多くのオブジェクト/DB 操作述語、グラフ アルゴリズム、およびその他の多くの考え方を提供します。プロジェクトの Web サイトでこれらすべてを表示できなくて申し訳ありません。私たちは主に商用プロジェクトでウランを使用しており、SF サイトは私の空き時間の子です。しかし、これはオープン ソースであり、共有できるドキュメントと例がたくさんあります。
私の答えがお役に立てば幸いです。