如何从geosparql的wktLiteral中检索纬度和经度?

时间:2014-03-20 14:44:15

标签: rdf geospatial sparql

我正在处理包含地理参考资料的RDF数据,例如具有指定位置的POI:

@prefix ogc:   <http://www.opengis.net/ont/geosparql#> .

:poi  ogc:hasGeometry  :geo
:geo  ogc:asWKT        "POINT(48.5 11.7)"^^ogc:wktLiteral .

所以有某种POI位于(48.5,11.7)。 我可以使用GeoSPARQL - 查询来处理这些位置,但现在我想分别提取纬度和经度,因此我可以将其提供给不支持WKT的其他应用程序。

SELECT ?lat ?lon
WHERE {
    # how do I get lat and lon from "POINT(48.5 11.7)"^^ogc:wktLiteral?
}

我在OGC's GeoSPARQL specification中找不到任何有用的东西,所以我想知道在SPARQL查询中手动提取这类数据的最佳方法是什么。

2 个答案:

答案 0 :(得分:3)

使用正则表达式做这类事情总是有点棘手,特别是当它看起来不像我们有一个精确的语法时,但我认为以下方法有效:

prefix ogc: <urn:ex:>

select ?lat ?long where {
  values ?point { "POINT(48.5 11.7)"^^ogc:wktLiteral }
  bind( replace( str(?point), "^[^0-9\\.]*([0-9\\.]+) .*$", "$1" ) as ?long )
  bind( replace( str(?point), "^.* ([0-9\\.]+)[^0-9\\.]*$", "$1" ) as ?lat )
}
-------------------
| lat    | long   |
===================
| "11.7" | "48.5" |
-------------------

这里的关键是正则表达式

"^[^0-9\\.]*([0-9\\.]+) .*$" === <non-number>(number) <anything>
"^.* ([0-9\\.]+)[^0-9\\.]*$" === <anything> (number)<non-number>

当然,这实际上是number的近似值,因为它可以匹配多个点的内容,但如果数据是好的,那么你应该没有问题。如果您需要将这些值转换为数字类型,您也可以执行此类转换:

prefix ogc: <urn:ex:>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>

select ?lat ?long where {
  values ?point { "POINT(48.5 11.7)"^^ogc:wktLiteral }
  bind( xsd:decimal( replace( str(?point), "^[^0-9\\.]*([0-9\\.]+) .*$", "$1" )) as ?long )
  bind( xsd:decimal( replace( str(?point), "^.* ([0-9\\.]+)[^0-9\\.]*$", "$1" )) as ?lat )
}
---------------
| lat  | long |
===============
| 11.7 | 48.5 |  # note: no quotation marks; these are numbers
---------------

请注意,还有其他类型的WKT点,此代码无法正确处理它们。例如,维基百科的Well-known text文章中的一些例子:

POINT ZM (1 1 5 60)
POINT M (1 1 80)
POINT EMPTY

答案 1 :(得分:0)

约书亚的回答没有考虑纬度或经度的负值。对此的更正是:

prefix ogc: <urn:ex:>
select ?lat ?long where {
   values ?point { "POINT(48.5 -11.7)"^^ogc:wktLiteral }
   bind( replace( str(?point), "^[^0-9\\.-]*([-]?[0-9\\.]+) .*$", "$1" ) as ?long )
   bind( replace( str(?point), "^.* ([-]?[0-9\\.]+)[^0-9\\.]*$", "$1" ) as ?lat )
}

和结果

--------------------
| lat     | long   |
===================
| "-11.7" | "48.5" |
--------------------

我已经使用议会SPARQL端点使用Rubular和GeoSPARQL查询测试了正则表达式,它似乎没问题。