2012-05-15 22 views
2

對於一個小實驗,我想將導出的OSM數據集從XML轉換爲Prolog。將OSM數據轉換爲Prolog的事實?

我知道有一些通用的XML到Prolog轉換器(例如,Pl4Xml),但這些通用轉換器是解決此問題的最佳方式嗎?可能有人知道一個庫將OSM數據轉換成方便表示在Prolog?

回答

2

塞爾吉奧,我不知道最好的方法。但是我用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個不同的標籤鍵。應該妥善處理。我認爲最好的方法是使用OSM節點的謂詞,方式和與普通tags成員的關係,並將一個標籤數據表示爲有序的一組鍵值對(或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定義一個類 - 這是一個通常的Prolog項與命名訪問的可能性值(帶額外的謂詞幫助)和許多其他事情,如繼承,對象數據庫等。該模塊定義了三個主要的OSM實體 - node_v,way_vrelation_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數據庫的對象數據庫(也可以在未來版本中使用外部PostgreSQL)。

一個解析結果的例子是:

?- 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 
) 

另外鈾提供了大量的對象/ DB操縱謂詞,圖形algorithmes和很多其他想。對不起,沒有在項目網站上顯示所有這些東西。我們主要在商業項目中使用鈾礦,SF礦場是我空閒時間的孩子。但它是開源的,我們有很多文檔和例子可供分享。

我希望我的回答很有用。