JHS 193 Unique identifiers of geographic data

Annex 2. Example of the technical implementation of the URI service of a data producer

  • Version: 1.0
  • Issued on: 2 September 2015
  • Validity: until further notice

    1 Introduction

This annex presents an example of the technical implementation of a URI service which gives a response in accordance with the responding practices defined in this recommendation. The below presented technical solutions used in the implementation are examples. A service producing a response in accordance with the responding practices can also be implemented in many other ways. Any optional implementation methods identified are presented in the body text.

Identifiers assigned to geographic features, real-world objects and concepts in accordance with this recommendation are located under the domain name paikkatiedot.fi. Paikkatiedot.fi acts as a national redirection service for URIs of geographic information which redirects incoming requests to the URI service offered by a data producer.

Requests concerning URIs should be redirected to the URI service offered by a data producer, the response received from which is in accordance with the responding practices defined in this recommendation. The general format of the URL (documentation identifier "doc", Chapter 9.1.4 of this recommendation) to which a query concerning the identifier of a geographic feature, real-world object or concept is redirected is:

http://{domain name}/doc/{dataset identifier}/{local identifier}[/{version identifier}]

    2 Operating principle and responding practices of the URI service

Image1

The paikkatiedot.fi redirection service redirects requests concerning the identifier of a geographic feature, real-world object or concept to the URI service of a data producer. The URI service returns documentation related to the geographic feature, real-world object or concept. In this example, the documentation is in RDF/XML format.

Documentation includes references

  • to the documented geographic feature, real-world object or concept;
  • to the different formats of portrayal (GML, JSON, etc.) of the specific geographic data feature if the documentation is related to a data feature (geographic feature or concept); and
  • as possible,
  • to a real-world object corresponding to the geographic feature,
  • to concepts representing the geographic feature or real-world object,
  • to another documented geographic feature, real-world object or geographic features, real-world objects, concepts or other documentation (images, texts, etc.) related to the geographic feature.

In this example, the URI service redirects queries of the portrayal formats of geographic features to the Web Feature Service, which returns information about the feature in the desired coordinate system and format. Different forms of portrayal of a geographic feature are presented in the following format:

http://{domain name}/doc/{dataset identifier}/{local identifier}/{coordinate system}.{format}

Example:

http://{domain name}/doc/{dataset identifier}/{local identifier}/EPSG:3087.gml2

A more detailed description of the structure of the RDF data returned by the URI service is presented in Chapter 5. Chapter 6.3 presents an example of RDF data in accordance with this structural description.

    3 Technical requirements

The following technologies have been used in the implementation of the URI service presented in this example:

  • Apache HTTP server
  • Apache Jena Fuseki RDF server

This annex does not offer any instructions for the implementation of Apache HTTP and Apache Jena Fuseki servers, as they have been presented on the websites of the products.

Apache Jena Fuseki server software follows the SPARQL 1.1 standard, and it can be replaced by any software following the same standard.

    4 Implementation stages of the URI service

An example of the stage-by-stage implementation of the URI service is presented below. All of the files used in this implementation are presented in Chapter 6.

  1. Create a SPARQL update script including the documentation related to geographic features in accordance with the RDF schema presented in Chapter 5. The script can be generated from the GML document returned by the GetFeature object query of WFS using the XSLT conversion. There are good applications for the definition and execution of the conversion available online. The XSLT conversion file used in this example implementation is presented in Chapter 6.1. If the geographic dataset is available up-to-date in the database and the aim is to avoid the processing of (possibly large) GML documents, the SPARQL update script can alternatively be generated directly from the database using a suitable script.
  2. Upload the documentation related to geographic features to the Apache Jena Fuseki RDF database using the SPARQL update clause generated in Section 1. Alternatively, the GML document (or the content of the database) in Section 1 can also be converted directly into RDF/XML format (using the XSLT conversion or another script), after which it can be uploaded to the RDF database using the SPARQL LOAD clause.
  3. Make a SPARQL query to the Apache Jena Fuseki database in accordance with Chapter 6.2. The query returns data in accordance with the RDF schema defined in Chapter 5. An example of this is presented in Chapter 6.3. Alternatively, auxiliary tools, such as Pubby (https://github.com/cygri/pubby) or Elda (https://github.com/epimorphics/elda), can also be used to release RDF data.
  4. Create a .htaccess file on the Apache HTTP server which is visible towards the Internet. Chapter 6.4 presents an example and a description of the Apache .htaccess redirection file.

Note: This is an example implementation performed in a specific environment. In addition to these stages, it may be necessary to perform several technical configurations, depending on the existing server environment and network infrastructure.

    5 Structural description of RDF data returned by the URI service

The table below presents a structural description of RDF data returned by the URI service. An example of an RDF response in accordance with this description is presented in Chapter 6.3.

Class

Property

Property value range

Recurrence

Description

jhs:Doc

Documentation related to a resource

jhs:so

Identifier of a geographic feature

0-1

If the documented resource is a geographic feature, a reference to the geographic feature to which the documentation is directed

jhs:id

Identifier of a real-world object

0-1

A reference to a real-world object which is modelled by the documented geographic feature

dct:hasFormat

jhs:Data

1-n

Available forms of portrayal of the resource

dct:subject

Concept identifier

0-n

A reference to a concept representing the resource

rdfs:seeAlso

Additional information related to a feature or concept

0–n

A reference, for example, to a geographic feature modelling the same real-world object

jhs:Data

Form of portrayal of the resource

jhs:CRS

Coordinate reference system of the form of portrayal

0-1

EPSG code of the coordinate reference system of the form of portrayal (for geographic features only)

dc:format

Format of the form of portrayal

1

MIME type of the form of portrayal

jhs:so

Identifier of a geographic feature

0-1

A reference to the presented geographic feature

jhs:def

Concept identifier

0-1

A reference to the presented geographic concept

Table 1. Structural description of RDF data returned by the URI service.

jhs: http://paikkatiedot.fi/jhs-skeema#

dc: http://purl.org/dc/elements/1.1/

dct: http://purl.org/dc/terms/

The producer of the URI service can freely apply the aforementioned RDF structure, for example, by expanding it with own elements. These include different types of links to other data features. The data content of a geographic feature or concept can also be added as part of RDF documentation.

    6 Example files

      6.1 XSLT conversion file

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:tampere_ora="http://www.navici.com/ns/tampere_ora" xmlns:gml="http://www.opengis.net/gml" >

<xsl:output method="text" indent="yes"/>

<xsl:template match="/">

PREFIX rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt;
PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
PREFIX dc: &lt;http://purl.org/dc/elements/1.1/&gt;
PREFIX jhs: &lt;http://paikkatiedot.fi/jhs-skeema#&gt;

<!-- Generate a SPARQL INSERT clause. In the INSERT clause, RDF triples are presented in Turtle format. -->

INSERT DATA {

<xsl:for-each select="//tampere_ora:1000358_WB">

<!-- Documentation related to the geographic feature -->

&lt;http://kartat.tampere.fi/uri/doc/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>&gt; rdf:type jhs:Doc;
jhs:so &lt;http://paikkatiedot.fi/so/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>&gt;;
jhs:id &lt;http://paikkatiedot.fi/id/1000040/<xsl:value-of select="tampere_ora:DIGIROAD_ID"/>&gt;;
rdfs:seeAlso &lt;http://paikkatiedot.fi/so/1000040/<xsl:value-of select="tampere_ora:DIGIROAD_ID"/>&gt;;
dct:hasFormat &lt;http://kartat.tampere.fi/uri/doc/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>/EPSG:3067.json&gt;;
dct:hasFormat &lt;http://kartat.tampere.fi/uri/doc/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>/EPSG:3067.gml2&gt;;
dct:hasFormat &lt;http://kartat.tampere.fi/uri/doc/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>/EPSG:3878.json&gt;;
dct:hasFormat &lt;http://kartat.tampere.fi/uri/doc/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>/EPSG:3878.gml2&gt;;
dct:subject &lt;http://www.yso.fi/onto/yso/p17892&gt;.

<!-- Forms of representation of the geographic feature -->

&lt;http://kartat.tampere.fi/uri/doc/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>/EPSG:3067.json&gt; rdf:type jhs:Data;
jhs:so &lt;http://paikkatiedot.fi/so/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>&gt;;
jhs:CRS &lt;http://www.opengis.net/def/crs/EPSG/0/3067&gt;;
dc:format "application/json".

&lt;http://kartat.tampere.fi/uri/doc/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>/EPSG:3067.gml2&gt; rdf:type jhs:Data;
jhs:so &lt;http://paikkatiedot.fi/so/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>&gt;;
jhs:CRS &lt;http://www.opengis.net/def/crs/EPSG/0/3067&gt;;
dc:format "application/gml".

&lt;http://kartat.tampere.fi/uri/doc/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>/EPSG:3878.json&gt; rdf:type jhs:Data;
jhs:so &lt;http://paikkatiedot.fi/so/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>&gt;;
jhs:CRS &lt;http://www.opengis.net/def/crs/EPSG/0/3878&gt;;
dc:format "application/json".

&lt;http://kartat.tampere.fi/uri/doc/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>/EPSG:3878.gml2&gt; rdf:type jhs:Data;
jhs:so &lt;http://paikkatiedot.fi/so/1000358/<xsl:value-of select="tampere_ora:TUNNISTE"/>&gt;;
jhs:CRS &lt;http://www.opengis.net/def/crs/EPSG/0/3878&gt;;
dc:format "application/gml".

</xsl:for-each>

}

</xsl:template>

</xsl:stylesheet>

      6.2 SPARQL query

PREFIX rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
PREFIX rdfs: http://www.w3.org/2000/01/rdf-schema#
PREFIX dc: http://purl.org/dc/elements/1.1/
PREFIX jhs: <http://paikkatiedot.fi/jhs-skeema#>

CONSTRUCT {

<http://kartat.tampere.fi/uri/doc/1000358/0072> jhs:so ?so;
rdf:type ?a;
jhs:id ?h;
rdfs:seeAlso ?g;
dct:subject ?b;
dct:hasFormat ?c.
?c jhs:CRS ?d.
?c dc:format ?e.
?c rdf:type ?f
} WHERE
{
<http://kartat.tampere.fi/uri/doc/1000358/0072> jhs:so ?so;
rdf:type ?a;
jhs:id ?h;
rdfs:seeAlso ?g;
dct:subject ?b;
dct:hasFormat ?c.
?c jhs:CRS ?d.
?c dc:format ?e.
?c rdf:type ?f

}

      6.3 RDF example

<rdf:RDF

xmlns:jhs="http://paikkatiedot.fi/jhs-skeema#"

xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"

xmlns:dc="http://purl.org/dc/elements/1.1/"

xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">

<jhs:Doc rdf:about="http://kartat.tampere.fi/uri/doc/1000358/6447">

<dct:hasFormat>

<jhs:Data rdf:about="http://kartat.tampere.fi/uri/doc/1000358/6447/EPSG:3067.json">

<dc:format>application/json</dc:format>

<jhs:CRS rdf:resource="http://www.opengis.net/def/crs/EPSG/0/3067"/>

</jhs:Data>

</dct:hasFormat>

<dct:hasFormat>

<jhs:Data rdf:about="http://kartat.tampere.fi/uri/doc/1000358/6447/EPSG:3067.gml2">

<dc:format>application/gml</dc:format>

<jhs:CRS rdf:resource="http://www.opengis.net/def/crs/EPSG/0/3067"/>

</jhs:Data>

</dct:hasFormat>

<dct:hasFormat>

<jhs:Data rdf:about="http://kartat.tampere.fi/uri/doc/1000358/6447/EPSG:3878.json">

<dc:format>application/json</dc:format>

<jhs:CRS rdf:resource="http://www.opengis.net/def/crs/EPSG/0/3878"/>

</jhs:Data>

</dct:hasFormat>

<dct:hasFormat>

<jhs:Data rdf:about="http://kartat.tampere.fi/uri/doc/1000358/6447/EPSG:3878.gml2">

<dc:format>application/gml</dc:format>

<jhs:CRS rdf:resource="http://www.opengis.net/def/crs/EPSG/0/3878"/>

</jhs:Data>

</dct:hasFormat>

<dct:subject rdf:resource="http://www.yso.fi/onto/yso/p17892"/>

<rdfs:seeAlso rdf:resource="http://paikkatiedot.fi/so/1000040/172353"/>

<jhs:id rdf:resource="http://paikkatiedot.fi/id/1000040/172353"/>

<jhs:so rdf:resource="http://paikkatiedot.fi/so/1000358/6447"/>

</jhs:Doc>

</rdf:RDF>

      6.4 Turtle example

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

@prefix jhs: <http://paikkatiedot.fi/jhs-skeema#> .

@prefix dc: <http://purl.org/dc/elements/1.1/> .

@prefix dct: <https://purl.org/dc/terms> .

@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

<http://kartat.tampere.fi/uri/doc/1000358/6447>

rdf:type jhs:doc ;

jhs:id <http://paikkatiedot.fi/id/1000040/172353> ;

jhs:so <http://paikkatiedot.fi/so/1000358/6447> ;

dc:subject <http://www.yso.fi/onto/yso/p17892> ;

rdfs:seeAlso <http://paikkatiedot.fi/so/1000040/172353> ;

dct:hasFormat <http://kartat.tampere.fi/uri/doc/1000358/6447/EPSG:3067.gml2> ;

dct:hasFormat <http://kartat.tampere.fi/uri/doc/1000358/6447/EPSG:3067.json> .

<http://kartat.tampere.fi/uri/doc/1000358/6447/EPSG:3067.gml2>

rdf:type jhs:data ;

jhs:CRS <http://www.opengis.net/def/crs/EPSG/0/3067> ;

dc:format "application/gml" .

<http://kartat.tampere.fi/uri/doc/1000358/6447/EPSG:3067.json>

rdf:type jhs:data ;

jhs:CRS <http://www.opengis.net/def/crs/EPSG/0/3067> ;

dc:format "application/json" .

      6.5 Apache .htaccess file

<IfModule mod_rewrite.c>

RewriteEngine On

Rewritebase /uri/

# RewriteRule redirects the doc path component's variables ([a-zA-Z0-9]+)/([a-zA-Z0-9:]+).([a-zA-Z0-9]+) to wfs target query $1,$2,$3. Note that RewriteRule must be on a single row, not in the format presented below.

RewriteRule ^doc/1000358/([a-zA-Z0-9_]+)/([a-zA-Z0-9:]+).([a-zA-Z0-9]+)$ http://tampere.navici.com/tampere_wfs_geoserver/tampere_ora/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=tampere_ora:BUSSIPYSAKIT_WB&outputformat=$3&srsName=$2&Filter=<Filter><PropertyIsEqualTo><PropertyName>TUNNISTE</PropertyName><Literal>$1</Literal></PropertyIsEqualTo></Filter>

RewriteRule ^doc/1000359/([a-zA-Z0-9_]+)/([a-zA-Z0-9:]+).([a-zA-Z0-9]+)$ http://tampere.navici.com/tampere_wfs_geoserver/tampere_ora/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=tampere_ora:BUSSILINJAT&outputformat=$3&srsName=$2&Filter=<Filter><PropertyIsEqualTo><PropertyName>REITTI</PropertyName><Literal>$1</Literal></PropertyIsEqualTo></Filter>

RewriteRule ^doc/1000378/([a-zA-Z0-9_-]+)/([a-zA-Z0-9:]+).([a-zA-Z0-9]+)$ http://tampere.navici.com/tampere_wfs_geoserver/rakennukset/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=rakennukset:RAKENN_ST_FA_MVIEW&outputformat=$3&srsName=$2&Filter=<Filter><PropertyIsEqualTo><PropertyName>RAK_TUNNUS_FACTA</PropertyName><Literal>$1</Literal></PropertyIsEqualTo></Filter>

RewriteRule ^doc/1000040/([a-zA-Z0-9_-]+)/([a-zA-Z0-9:]+).([a-zA-Z0-9]+)$ https://extranet.liikennevirasto.fi/inspirepalvelu/maaliikenne_avoin/wfs?request=GetFeature&typeName=maaliikenne_avoin:bussipysakit&srsName=$2&Filter=<Filter><PropertyIsLike+wildCard="*"+singleChar=","+escapeChar="."><PropertyName>STOP_ID</PropertyName><Literal>$1</Literal></PropertyIsLike></Filter>&outputformat=$3

#RewriteRule redirects the doc path component's variable ([a-zA-Z0-9]+) to SPARQL query $1. Note that RewriteRule must be on a single row, not in the format presented below.

RewriteRule ^doc/1000358/([a-zA-Z0-9_-]+)$ http://kartat.tampere.fi/fuseki/ds2/query?query=PREFIX+rdf:+<http://www.w3.org/1999/02/22-rdf-syntax-ns#>PREFIX+rdfs:+<http://www.w3.org/2000/01/rdf-schema#>PREFIX+dc:+<http://purl.org/dc/elements/1.1/>PREFIX+jhs:+<http://paikkatiedot.fi/jhs-skeema#>CONSTRUCT+{<http://kartat.tampere.fi/uri/doc/1000358/$1>+jhs:so+?jep;rdf:type+?f;jhs:id+?h;rdfs:seeAlso+?g;dct:subject+?a;dct:hasFormat+?b.?b+jhs:CRS+?c.?b+dc:format+?d.?b+rdf:type+?e}+WHERE{<http://kartat.tampere.fi/uri/doc/1000358/$1>+jhs:so+?jep;rdf:type+?f;jhs:id+?h;rdfs:seeAlso+?g;dct:subject+?a;dct:hasFormat+?b.?b+jhs:CRS+?c.?b+dc:format+?d.?b+rdf:type+?e}+&output=xml

RewriteRule ^doc/1000358/([a-zA-Z0-9_-]+)/$ http://kartat.tampere.fi/fuseki/ds2/query?query=PREFIX+rdf:+<http://www.w3.org/1999/02/22-rdf-syntax-ns#>PREFIX+rdfs:+<http://www.w3.org/2000/01/rdf-schema#>PREFIX+dc:+<http://purl.org/dc/elements/1.1/>PREFIX+jhs:+<http://paikkatiedot.fi/jhs-skeema#>CONSTRUCT+{<http://kartat.tampere.fi/uri/doc/1000358/$1>+jhs:so+?jep;rdf:type+?f;jhs:id+?h;rdfs:seeAlso+?g;dct:subject+?a;dct:hasFormat+?b.?b+jhs:CRS+?c.?b+dc:format+?d.?b+rdf:type+?e}+WHERE{<http://kartat.tampere.fi/uri/doc/1000358/$1>+jhs:so+?jep;rdf:type+?f;jhs:id+?h;rdfs:seeAlso+?g;dct:subject+?a;dct:hasFormat+?b.?b+jhs:CRS+?c.?b+dc:format+?d.?b+rdf:type+?e}+&output=xml

RewriteRule ^doc/1000040/([a-zA-Z0-9_-]+)$ http://kartat.tampere.fi/fuseki/ds2/query?query=PREFIX+rdf:+<http://www.w3.org/1999/02/22-rdf-syntax-ns#>PREFIX+rdfs:+<http://www.w3.org/2000/01/rdf-schema#>PREFIX+dc:+<http://purl.org/dc/elements/1.1/>PREFIX+jhs:+<http://paikkatiedot.fi/jhs-skeema#>CONSTRUCT+{<http://kartat.tampere.fi/uri/doc/1000040/$1>+jhs:so+?jep;rdf:type+?f;jhs:id+?h;rdfs:seeAlso+?g;dct:subject+?a;dct:hasFormat+?b.?b+jhs:CRS+?c.?b+dc:format+?d.?b+rdf:type+?e}+WHERE{<http://kartat.tampere.fi/uri/doc/1000040/$1>+jhs:so+?jep;rdf:type+?f;jhs:id+?h;rdfs:seeAlso+?g;dct:subject+?a;dct:hasFormat+?b.?b+jhs:CRS+?c.?b+dc:format+?d.?b+rdf:type+?e}+&output=xml

RewriteRule ^doc/1000040/([a-zA-Z0-9_-]+)/$ http://kartat.tampere.fi/fuseki/ds2/query?query=PREFIX+rdf:+<http://www.w3.org/1999/02/22-rdf-syntax-ns#>PREFIX+rdfs:+<http://www.w3.org/2000/01/rdf-schema#>PREFIX+dc:+<http://purl.org/dc/elements/1.1/>PREFIX+jhs:+<http://paikkatiedot.fi/jhs-skeema#>CONSTRUCT+{<http://kartat.tampere.fi/uri/doc/1000040/$1>+jhs:so+?jep;rdf:type+?f;jhs:id+?h;rdfs:seeAlso+?g;dct:subject+?a;dct:hasFormat+?b.?b+jhs:CRS+?c.?b+dc:format+?d.?b+rdf:type+?e}+WHERE{<http://kartat.tampere.fi/uri/doc/1000040/$1>+jhs:so+?jep;rdf:type+?f;jhs:id+?h;rdfs:seeAlso+?g;dct:subject+?a;dct:hasFormat+?b.?b+jhs:CRS+?c.?b+dc:format+?d.?b+rdf:type+?e}+&output=xml

</IfModule>