Skip to content
This repository
csv2rdf4lod-automation is licensed under the Apache License, Version 2.0

What is first

Implementations of the technique introduced on this page:

  • in XSL: sparql-service-descriptions.xsl (key function shown below).
  • in python: DataFAQs' named-graphs.py FAqT Service
  • in bash / perl: resource-name.sh --named-graph <endpoint> <graph-name> (this was a predecessor that got most of the way).
  • in Java: implemented in csv2rdf4lod.jar/edu.rpi.tw.string.NameFactory#getSPARQLEndpointGraphName(String endpoint, String named_graph)

Example applications of naming a SPARQL service's named graph:

What we will cover

http://www.w3.org/TR/sparql11-service-description is a draft document describing how to describe what a SPARQL endpoint "is or can do". For example "do you accept SPARQL 1.1 queries?", and "what named graphs do you have?". This page is about the latter. In the examples that Greg and Ivan provide, blank nodes are used to (not) name the sd:NamedGraph instances that pair the named graphs in a SPARQL service with the SPARQL service itself (note that a named graph's name within two different endpoints ARE DISTINCT, and BOTH are distinct with the resource itself outside of the context of a SPARQL service).

However, I need to give the sd:NamedGraph a URI so that I can refer to it when describing the provenance of data loaded into the named graph. Is there a "good" URI we can use? YES! This page describes how to create a canonical URI for a sd:NamedGraph that conforms to Linked Data principles and nicely uses the SPARQL service itself to provide the functionality. The approach reuses the SPARQL endpoint's namespace to provide a nice canonical method to name any of its named graphs -- without inappropriately stomping on someone else's namespace.

Let's get to it!

SPARQL Service Description

An illustration of the full vocabulary:

An illustration of the example provided at http://www.w3.org/TR/sparql11-service-description/#example-turtle:

Getting started

sparql-service-descriptions.xsl queries a SPARQL endpoint for all named graphs and returns a SPARQL Service Description.

Loading the following RDF into http://logd.tw.rpi.edu:8890/sparql's named graph https://github.com/timrdf/csv2rdf4lod-automation/wiki/Naming-sparql-service-description%27s-sd%3ANamedGraph (Apologies for this endpoint not abstracting away from implementation details (i.e., its port)):

@prefix sd: <http://www.w3.org/ns/sparql-service-description#> .

[] a sd:Service; 
   sd:url <http://logd.tw.rpi.edu:8890/sparql>;
   sd:defaultDatasetDescription [
      a sd:Dataset;
      sd:namedGraph [
         a sd:NamedGraph;
         sd:name 
      <https://github.com/timrdf/csv2rdf4lod-automation/wiki/Naming-sparql-service-description%27s-sd%3ANamedGraph>;
      ];
  ]
.

We can query it to get an RDF description of where it is (i.e, the named graph of a particular SPARQL endpoint) (results):

PREFIX sd: <http://www.w3.org/ns/sparql-service-description#>

CONSTRUCT { ?endpoints_named_graph ?p ?o }
WHERE {
  GRAPH 
  <https://github.com/timrdf/csv2rdf4lod-automation/wiki/Naming-sparql-service-description%27s-sd%3ANamedGraph> {
     [] sd:url <http://logd.tw.rpi.edu:8890/sparql>;
        sd:defaultDatasetDescription [
           sd:namedGraph ?endpoints_named_graph
        ]
     .
     ?endpoints_named_graph 
        sd:name 
     <https://github.com/timrdf/csv2rdf4lod-automation/wiki/Naming-sparql-service-description%27s-sd%3ANamedGraph>;
        ?p ?o .
   }
}

Cleaning out the junk variables bundled into the URL:

http://logd.tw.rpi.edu:8890/sparql?query=PREFIX+sd%3A+%3Chttp%3A%2F%2Fwww.w3.org%2Fns%2Fsparql-service-description%23%3E%0D%0A%0D%0ACONSTRUCT+%7B+%3Fendpoints_named_graph+%3Fp+%3Fo+%7D%0D%0AWHERE+%7B%0D%0A++GRAPH+%0D%0A++%3Chttps%3A%2F%2Fgithub.com%2Ftimrdf%2Fcsv2rdf4lod-automation%2Fwiki%2FNaming-sparql-service-description%2527s-sd%253ANamedGraph%3E+%7B%0D%0A+++++%5B%5D+sd%3Aurl+%3Chttp%3A%2F%2Flogd.tw.rpi.edu%3A8890%2Fsparql%3E%3B%0D%0A++++++++sd%3AdefaultDatasetDescription+%5B%0D%0A+++++++++++sd%3AnamedGraph+%3Fendpoints_named_graph%0D%0A++++++++%5D%0D%0A+++++.%0D%0A+++++%3Fendpoints_named_graph+%0D%0A++++++++sd%3Aname+%0D%0A+++++%3Chttps%3A%2F%2Fgithub.com%2Ftimrdf%2Fcsv2rdf4lod-automation%2Fwiki%2FNaming-sparql-service-description%2527s-sd%253ANamedGraph%3E%3B%0D%0A++++++++%3Fp+%3Fo+.%0D%0A+++%7D%0D%0A%7D%0D%0A

and normalizing its white space, we now have a generic way to create a URI for a named graph within a particular SPARQL endpoint:

http://logd.tw.rpi.edu:8890/sparql?query=PREFIX%20sd%3A%20%3Chttp%3A%2F%2Fwww.w3.org%2Fns%2Fsparql-service-description%23%3E%20CONSTRUCT%20%7B%20%3Fendpoints_named_graph%20%3Fp%20%3Fo%20%7D%20WHERE%20%7B%20GRAPH%20%3Chttps%3A%2F%2Fgithub.com%2Ftimrdf%2Fcsv2rdf4lod-automation%2Fwiki%2FNaming-sparql-service-description%2527s-sd%253ANamedGraph%3E%20%7B%20%5B%5D%20sd%3Aurl%20%3Chttp%3A%2F%2Flogd.tw.rpi.edu%3A8890%2Fsparql%3E%3B%20sd%3AdefaultDatasetDescription%20%5B%20sd%3AnamedGraph%20%3Fendpoints_named_graph%20%5D%20.%20%3Fendpoints_named_graph%20sd%3Aname%20%3Chttps%3A%2F%2Fgithub.com%2Ftimrdf%2Fcsv2rdf4lod-automation%2Fwiki%2FNaming-sparql-service-description%2527s-sd%253ANamedGraph%3E%3B%20%3Fp%20%3Fo%20.%20%7D%20%7D

Now, if the SPARQL service has the named graph, and a service description is within this named graph describing itself, then a snippet of RDF will be returned when requesting the named graph's URI. Note that the service description doesn't actually need to be in the named graph for the URI to be "valid" (since "valid" doesn't even make sense) -- it just means that IF it were there, THEN we'd get some "interesting" RDF back describing it. The perfect canonical URI, created by anyone and responsive without modification to the SPARQL service implementation.

An XSL 2.0 function that implements the canonical URI for a sd:NamedGraph given the endpoint that hosts it and the sd:name:

<xsl:function name="vsr:name-sparql-endpoints-named-graph">
   <xsl:param name="endpoint"/>
   <xsl:param name="named-graph"/>
   <xsl:variable name="query-constructing-named-graph-description">
      PREFIX sd: &lt;http://www.w3.org/ns/sparql-service-description#>

      CONSTRUCT { ?endpoints_named_graph ?p ?o }
      WHERE {
        GRAPH 
        ?:NAMED_GRAPH {
           [] sd:url ?:ENDPOINT;
              sd:defaultDatasetDescription [
                 sd:namedGraph ?endpoints_named_graph
              ]
           .
           ?endpoints_named_graph 
              sd:name 
           ?:NAMED_GRAPH;
              ?p ?o .
         }
      }
   </xsl:variable>
   <xsl:value-of select="concat($endpoint,
                                       '?query=',
                                       encode-for-uri(
                                       normalize-space(
                                       vsr:bind-variable(
                                       vsr:bind-variable($query-constructing-named-graph-description,
                                                        'ENDPOINT',   concat('&lt;',$endpoint,'>')),
                                                        'NAMED_GRAPH',concat('&lt;',$named-graph,'>')))))"/>
</xsl:function>

Locating a sd:NamedGraph - template

For graph named <name> (cf. SELECT * WHERE { GRAPH {} } ) available for query from endpoint <endpoint> (cf. endpoint?query="@prefix"):

@prefix void: <http://rdfs.org/ns/void#> .
@prefix sd:   <http://www.w3.org/ns/sparql-service-description#> .
@prefix :     <#> .

:service 
   a sd:Service;
   sd:endpoint <endpoint>;        # <-- Fill this in.
   sd:availableGraphs :collection;
.
:collection
   a sd:GraphCollection;
   sd:namedGraph :named-graph;
.
:named-graph
   a sd:NamedGraph;
   sd:name <name>;                # <-- Fill this in.
   sd:graph :graph;
.
:graph
   a sd:Graph, void:Dataset;
   void:triples 10;               # Or however many are in the abstract graph.
   void:dataDump <file>;          # Some RDF file that has 10 triples in it.
.

https://github.com/timrdf/DataFAQs/tree/master/services/sadi/ckan/add-metadata-materials/sample-inputs shows examples for how to model a service, named graph, and dataset. The examples are sample inputs for add-metadata.py, a service to update CKAN given a good RDF description of the datafaqs:CKANDataset.

TODO: discuss http://www.w3.org/TR/sparql11-http-rdf-update/#indirect-graph-identification

What is next

Something went wrong with that request. Please try again.