【问题标题】:Converting OSM data to Prolog facts?将 OSM 数据转换为 Prolog 事实?
【发布时间】:2012-05-17 17:56:38
【问题描述】:

对于一个小型实验,我想将导出的 OSM 数据集从 XML 转换为 Prolog。

我知道有某些通用 XML 到 Prolog 转换器(例如,Pl4Xml),但是这些通用转换器是解决这个问题的最佳方法吗?可能有人知道将 OSM 数据转换为 Prolog 中方便表示的库?

【问题讨论】:

    标签: prolog converter openstreetmap


    【解决方案1】:

    塞尔吉奥,我不知道最好的方法。但是我用 OSM 做了我自己的小实验。我没有使用 Pl4XML,而只是使用带有库(sgml)的 SWI-Prolog。像这样:

    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 定义了一个类 - 它是一个常用的序言术语,可以命名访问值(在附加谓词的帮助下)和许多其他东西,如继承、对象数据库等。该模块定义了三个主要的 OSM 实体- node_vway_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)。

    nodes - 是一个基于标准 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 
    )
    

    Uranium 还提供了许多对象/数据库操作谓词、图形算法和许多其他思想。很抱歉没有在项目网站上显示所有这些内容。我们主要在商业项目中使用铀,SF 网站是我空闲时间的孩子。但它是开源的,我们有很多文档和示例可以分享。

    希望我的回答有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-14
      • 1970-01-01
      • 1970-01-01
      • 2013-02-24
      • 1970-01-01
      相关资源
      最近更新 更多