summaryrefslogtreecommitdiff
path: root/docs/namespaces_and_bindings.rst
blob: ef7458661c55b8ca00db367405a567804a2fd77f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
.. _namespaces_and_bindings: Namespaces and Bindings

=======================
Namespaces and Bindings
=======================

RDFLib provides several short-cuts to working with many URIs in the same namespace. 

The :mod:`rdflib.namespace` defines the :class:`rdflib.namespace.Namespace` class which lets you easily create URIs in a namespace::

	from rdflib import Namespace

	EX = Namespace("http://example.org/")
	EX.Person  # a Python attribute for EX. This example is equivalent to rdflib.term.URIRef("http://example.org/Person")

    # use dict notation for things that are not valid Python identifiers, e.g.:
	n['first%20name']  # as rdflib.term.URIRef("http://example.org/first%20name")

These two styles of namespace creation - object attribute and dict - are equivalent and are made available just to allow for valid
RDF namespaces and URIs that are not valid Python identifiers. This isn't just for syntactic things like spaces, as per 
the example of ``first%20name`` above, but also for Python reserved words like ``class`` or ``while``, so for the URI 
``http://example.org/class``, create it with ``EX['class']``, not ``EX.class``.

Common Namespaces
-----------------

The ``namespace`` module defines many common namespaces such as RDF, RDFS, OWL, FOAF, SKOS, PROF, etc. The list of the 
namespaces provided grows with user contributions to RDFLib.

These Namespaces, and any others that users define, can also be associated with prefixes using the :class:`rdflib.namespace.NamespaceManager`, e.g. using ``foaf`` for ``http://xmlns.com/foaf/0.1/``.

Each RDFLib graph has a :attr:`~rdflib.graph.Graph.namespace_manager` that keeps a list of namespace to prefix mappings. The namespace manager is populated when reading in RDF, and these prefixes are used when serialising RDF, or when parsing SPARQL queries. Prefixes can be bound with the :meth:`rdflib.graph.Graph.bind` method::

    from rdflib import Graph, Namespace
    from rdflib.namespace import FOAF
    
    EX = Namespace("http://example.org/")
    
    g = Graph()
    g.bind("foaf", FOAF)  # bind an RDFLib-provided namespace to a prefix
    g.bind("ex", EX)      # bind a user-declared namespace to a prefix
    

The :meth:`rdflib.graph.Graph.bind` method is actually supplied by the :class:`rdflib.namespace.NamespaceManager` class - see next.

NamespaceManager
----------------

Each RDFLib graph comes with a :class:`rdflib.namespace.NamespaceManager` instance in the :attr:`~rdflib.graph.Graph.namespace_manager` field; you can use the :meth:`~rdflib.namespace.NamespaceManager.bind` method of this instance to bind a prefix to a namespace URI,
as above, however note that the :class:`~rdflib.namespace.NamespaceManager` automatically performs some bindings according to a selected strategy. 

Namespace binding strategies are indicated with the ``bind_namespaces`` input parameter to :class:`~rdflib.namespace.NamespaceManager` instances 
and may be set via ``Graph`` also::

    from rdflib import Graph
    from rdflib.namespace import NamespaceManager
    
    g = Graph(bind_namespaces="rdflib")  # bind via Graph
    
    g2 = Graph()
    nm = NamespaceManager(g2, bind_namespaces="rdflib")  # bind via NamespaceManager


Valid strategies are:

* core:
    * binds several core RDF prefixes only
    * owl, rdf, rdfs, xsd, xml from the NAMESPACE_PREFIXES_CORE object
    * this is default
* rdflib:
    * binds all the namespaces shipped with RDFLib as DefinedNamespace instances
    * all the core namespaces and all the following: brick, csvw, dc, dcat
    * dcmitype, dcterms, dcam, doap, foaf, geo, odrl, org, prof, prov, qb, sdo
    * sh, skos, sosa, ssn, time, vann, void
    * see the NAMESPACE_PREFIXES_RDFLIB object in :class:`rdflib.namespace` for up-to-date list
* none:
    * binds no namespaces to prefixes
    * note this is NOT default behaviour
* cc:
    * using prefix bindings from prefix.cc which is a online prefixes database
    * not implemented yet - this is aspirational

Re-binding
^^^^^^^^^^

Note that regardless of the strategy employed, prefixes for namespaces can be overwritten with users preferred prefixes,
for example::

    from rdflib import Graph
    from rdflib.namespace import GEO  # imports GeoSPARQL's namespace
    
    g = Graph(bind_namespaces="rdflib")  # binds GeoSPARQL's namespace to prefix 'geo'
    
    g.bind('geosp', GEO, override=True) 
    
    

:class:`~rdflib.namespace.NamespaceManager` also has a method to normalize a given url::

    from rdflib.namespace import NamespaceManager
    
    nm = NamespaceManager(Graph())
    nm.normalizeUri(t)


For simple output, or simple serialisation, you often want a nice
readable representation of a term.  All RDFLib terms have a
``.n3()`` method, which will return a suitable N3 format and into which you can supply a NamespaceManager instance
to provide prefixes, i.e. ``.n3(namespace_manager=some_nm)``::

   >>> from rdflib import Graph, URIRef, Literal, BNode
   >>> from rdflib.namespace import FOAF, NamespaceManager

   >>> person = URIRef("http://xmlns.com/foaf/0.1/Person")
   >>> person.n3()
   '<http://xmlns.com/foaf/0.1/Person>'

   >>> g = Graph()
   >>> g.bind("foaf", FOAF)

   >>> person.n3(g.namespace_manager)
   'foaf:Person'

   >>> l = Literal(2)
   >>> l.n3()
   '"2"^^<http://www.w3.org/2001/XMLSchema#integer>'
   
   >>> l.n3(NamespaceManager(Graph(), bind_namespaces="core"))
   '"2"^^xsd:integer'
   
The namespace manage also has a useful method ``compute_qname``
``g.namespace_manager.compute_qname(x)`` (or just ``g.compute_qname(x)``) which takes a URI and decomposes it into the parts::

    self.assertEqual(g.compute_qname(URIRef("http://foo/bar#baz")),
	            ("ns2", URIRef("http://foo/bar#"), "baz"))
   


Namespaces in SPARQL Queries
----------------------------

The ``initNs`` argument supplied to :meth:`~rdflib.graph.Graph.query` is a dictionary of namespaces to be expanded in the query string. 
If you pass no ``initNs`` argument, the namespaces registered with the graphs namespace_manager are used::

    from rdflib.namespace import FOAF
    graph.query('SELECT * WHERE { ?p a foaf:Person }', initNs={'foaf': FOAF})


In order to use an empty prefix (e.g. ``?a :knows ?b``), use a ``PREFIX`` directive with no prefix in the SPARQL query to set a default namespace:

.. code-block:: sparql

    PREFIX : <http://xmlns.com/foaf/0.1/>