How do I convert a rdflib.term.URIRef back into a string that includes a namespace prefix?

926 Views Asked by At

I am working with rdflib. I am parsing Turtle files that include namespace prefixes. When I get my triples back from the SPARQL query, they contain rdflib.term.URIRef elements, which print as things like this:

http://resources.data.gov/resources/dcat-us/#public

My rdflib graph knows that usg: is a namespace prefix for http://resources.data.gov/resources/dcat-us/# . I would like to convert http://resources.data.gov/resources/dcat-us/#public back to usg:public on printing.

MWE

Here is a file mwe_schema.ttl:

@prefix usg:  <http://resources.data.gov/resources/dcat-us/#> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .
@prefix dcat: <http://www.w3.org/ns/dcat#> .
@prefix dct:  <http://purl.org/dc/terms/#> .

usg:public
    a rdfs:Property ;
    rdfs:label "public"@en ;
    rdfs:comment "Data asset is or could be made publicly available to all without restrictions." ;
    .

Here is a program mwe_demo.py:

#!/usr/bin/env demonstrate python namespaces

import rdflib
from rdflib import Dataset, Graph, URIRef, Literal, Namespace, BNode

if __name__=="__main__":
    g    = Graph()
    g.parse("mwe_schema.ttl")
    for r in g.query(
            """
            SELECT DISTINCT ?aSubject ?aPredicate ?anObject
            WHERE {
            ?aSubject ?aPredicate ?anObject
            }
            """):
        d = r.asdict()
        print(d['aSubject'],d['aPredicate'],d['anObject'])

Here is the actual output:

http://resources.data.gov/resources/dcat-us/#public http://www.w3.org/2000/01/rdf-schema#comment Data asset is or could be made publicly available to all without restrictions.
http://resources.data.gov/resources/dcat-us/#public http://www.w3.org/1999/02/22-rdf-syntax-ns#type http://www.w3.org/2000/01/rdf-schema#Property
http://resources.data.gov/resources/dcat-us/#public http://www.w3.org/2000/01/rdf-schema#label public

Here is my desired output:

usg:public rdfs:comment  rdfs:Property
usg:public http://www.w3.org/1999/02/22-rdf-syntax-ns#type rdfs:Property
usg:public rdfs:label public

(I will separately handle turning the last public into `"public"@en).

1

There are 1 best solutions below

1
On BEST ANSWER

Results from SPARQL queries are not themselves RDF but SPARQL Results formats (see https://www.w3.org/TR/2013/REC-sparql11-results-json-20130321/).

This means results like http://resources.data.gov/resources/dcat-us/#public are strings in JSON or XML and not RDFlib's URIRef objects which can easily be prefixed.

To compress those URIs down with the given prefixes, don't SPARQL query but loop through the graph and use the Namespace Manager's qname() function like this:

    for s, p, o in g:
        for x in [s, p, o]:
            print(g.qname(x) if isinstance(x, URIRef) else x, end=" ")
        print()

If you really want to compress SPARQL results, you will have to use a CONSTRUCT query that returns an RDF graph, not a SPARQL Results output.