1

I have a RDFlib graph g, whose NameSpaceManager is aware of some namespaces.

How do I get a URIRef from a string such as 'ns:xxx', where ns is the prefix associated to a namespace known by g.namespace_manager? Basically, I'm looking for a method which does the inverse operation of URIRef's n3(g.namespace_manager). I'm pretty confident that there is a way to do it, as a similar function is needed to parse turtle files, or sparql queries, but I can't find it. Otherwise of course, it must not be very difficult to write it.

TIA

Progman
  • 16,827
  • 6
  • 33
  • 48
fps
  • 33
  • 7

2 Answers2

1
from rdflib import Graph, Namespace
from rdflib.namespace import RDF

g = Graph()
NS = Namespace("http://example.com/")

# then, say Xxx is a class and Aaa is an instance of Xxx...
g.add((NS.Aaa, RDF.type, NS.Xxx))

# so use NS.Xxx (or NS["Xxx"]) to get a URIRef of NS.Xxx from Namespace NS
print(type(NS))     # --> <class 'rdflib.term.URIRef'>
print(type(NS.Xxx)) # --> <class 'rdflib.term.URIRef'>
print(NS.Xxx)       # --> "http://example.com/Xxx"

If you want to bind a prefix within a graph, you use the rdflib Graph class' bind() method so, for the code above, you would use:

g.bind("ns", NS)

Now the graph, if serialized with a format that knows about prefixes, like Turtle, will use "ns". The above data would be:

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

ns:Aaa rdf:type ns:Xxx .

So, in Python, if you want to make the URI "http://example.com/Xxx"" from the string "ns:Xxx" you should have everything you need:

  • the namespace declaration: NS = Namespace("http://example.com/")
  • the prefix/namespace binding g.bind("ns", NS)

IFF, on the other hand, you didn't declare the namespace yourself but it's in a graph and you only have the short form URI "ns:Xxx", you can do this to list all bound prefixes & namespaces used in the graph:

for n in g.namespace_manager.namespaces():
    print(n)

returns, for the data above:

('xml', rdflib.term.URIRef('http://www.w3.org/XML/1998/namespace'))
('rdf', rdflib.term.URIRef('http://www.w3.org/1999/02/22-rdf-syntax-ns#'))
('rdfs', rdflib.term.URIRef('http://www.w3.org/2000/01/rdf-schema#'))
('xsd', rdflib.term.URIRef('http://www.w3.org/2001/XMLSchema#'))
('eg', rdflib.term.URIRef('http://example.com/'))

So, if you know "eg:Xxx", you can split off the "eg" part and make the URI you want like this:

print(
    [str(x[1]) for x in g.namespace_manager.namespaces() if x[0] == s.split(":")[0]]
    [0] + s.split(":")[1]
)

prints:

http://example.com/Xxx
Nicholas Car
  • 1,164
  • 4
  • 7
  • Hi Nicholas, thank you. I was asking myself whether RDFLib had this code involving the loop over namespaces and the s.split(":") already packed in one method. Your way to do is nicer than mine, and I appreciate your explanations about the API. Best Regards – fps Aug 06 '20 at 15:08
0
from rdflib.namespace import NamespaceManager
import rdflib as rdflib

class MyNamespacesInfo:
    def __init__(self, namespace_manager: NamespaceManager):
        # as I don't know how to get the namespace from a prefix from the API
        # I construct a dict
        self.pref2ns = {}
        for pref, ns in namespace_manager.namespaces():
            self.pref2ns[pref] = ns
    
    def uriref(self, n3uri: str) -> rdflib.URIRef:
        # n3uri: either 'ns:xxx', '<http://..../xxx>' or 'http://..../xxx'
        if n3uri[0] == '<':
            if n3uri[len(n3uri)-1] == '>':
                return rdflib.URIRef(n3uri[1:-1])
            else:
                raise ValueError("Illegal uri: ", n3uri)
        else:
            return self.prefixed_2_uriref(n3uri, laxist=True)

    def prefixed_2_uriref(self, short_uri: str, laxist=True) -> rdflib.URIRef:
        # param short_uri eg. 'ns:xxx', where ns declared in namespace_manager
        # using laxist = True, you also can pass a long uri
        s = short_uri.split(':')
        if len(s) < 2:
            if laxist:
                return rdflib.URIRef(short_uri)
            else:
                raise ValueError('Not a prefix:localname string: ' + short_uri)
        prefix = s[0]
        ns = self.pref2ns.get(prefix)
        if ns == None:
            if laxist:
                return rdflib.URIRef(short_uri)
            else:
                raise ValueError('Unknown prefix: ' + prefix)
        else:
            x = ns + s[1]
            for i in range(2, len(s)):
                x = x + (':' + s[i])
            return x

# example of use:

g = rdflib.Graph()
g.parse('http://www.semanlink.net/tag/rdf_tools.rdf')
ns_info = MyNamespacesInfo(g.namespace_manager)

# all of following calls print http://www.semanlink.net/tag/rdflib

x = ns_info.uriref('tag:rdflib')
print(x)
x = ns_info.uriref('http://www.semanlink.net/tag/rdflib')
print(x)
x = ns_info.uriref('<http://www.semanlink.net/tag/rdflib>')
print(x)
fps
  • 33
  • 7