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

kla*_*ann 4 rdf sparql geospatial

我正在使用包含地理参考内容的 RDF 数据,例如具有指定位置的 POI:

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

:poi  ogc:hasGeometry  :geo
:geo  ogc:asWKT        "POINT(48.5 11.7)"^^ogc:wktLiteral .
Run Code Online (Sandbox Code Playgroud)

所以有某种 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?
}
Run Code Online (Sandbox Code Playgroud)

我在OGC 的 GeoSPARQL 规范中没有找到任何有用的内容,因此我想知道在 SPARQL 查询中手动提取此类数据的最佳方法是什么。

Jos*_*lor 5

使用正则表达式做这类事情总是有点棘手,特别是当我们看起来没有精确的语法可以使用时,但我认为以下方法有效(注意:这仅适用于正值;请参阅其他答案,了解也适用于负值的模式):

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 )
}
Run Code Online (Sandbox Code Playgroud)
-------------------
| lat    | long   |
===================
| "11.7" | "48.5" |
-------------------
Run Code Online (Sandbox Code Playgroud)

这里的关键在于正则表达式

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

当然,这实际上是 的近似值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 )
}
Run Code Online (Sandbox Code Playgroud)
---------------
| lat  | long |
===============
| 11.7 | 48.5 |  # note: no quotation marks; these are numbers
---------------
Run Code Online (Sandbox Code Playgroud)

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

POINT ZM (1 1 5 60)
POINT M (1 1 80)
POINT EMPTY
Run Code Online (Sandbox Code Playgroud)