将OSM数据转换为Prolog事实



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

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

塞尔吉奥,我不知道最好的方法。但我用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 定义了一个类 - 它是一个通常的 prolog 术语,可以命名访问值(借助其他谓词(和许多其他东西,如继承、对象数据库等。该模块定义了三个主要的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网站是我空闲时间的孩子。但它是开源的,我们有很多文档和示例可以分享。

我希望我的回答是有用的。

最新更新