diff options
| author | Gunnar Aastrand Grimnes <gromgull@gmail.com> | 2013-05-09 21:23:11 +0200 |
|---|---|---|
| committer | Gunnar Aastrand Grimnes <gromgull@gmail.com> | 2013-05-09 21:23:11 +0200 |
| commit | 81de454ddeb29ed8b8e08864fca97eb577b3ce0c (patch) | |
| tree | dd82bfe5b6aab7e3b54441ca733549a7b811dc90 /docs | |
| parent | 7698d1b5d1b5bc9df82f5de99a7db3b853a0b2f9 (diff) | |
| download | rdflib-81de454ddeb29ed8b8e08864fca97eb577b3ce0c.tar.gz | |
doc-updates
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/conf.py | 16 | ||||
| -rw-r--r-- | docs/gettingstarted.rst | 47 | ||||
| -rw-r--r-- | docs/graphs_bnodes.rst | 468 | ||||
| -rw-r--r-- | docs/index.rst | 2 | ||||
| -rw-r--r-- | docs/intro_to_creating_rdf.rst | 93 | ||||
| -rw-r--r-- | docs/intro_to_graphs.rst | 77 | ||||
| -rw-r--r-- | docs/intro_to_parsing.rst | 38 | ||||
| -rw-r--r-- | docs/intro_to_sparql.rst | 25 | ||||
| -rw-r--r-- | docs/namespaces_and_bindings.rst | 30 | ||||
| -rw-r--r-- | docs/rdf_terms.rst | 3 |
10 files changed, 194 insertions, 605 deletions
diff --git a/docs/conf.py b/docs/conf.py index e1ad76d1..d798ef30 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,19 +23,21 @@ import sys, os, re # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. # extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.doctest'] -extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', 'sphinx.ext.coverage', - 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode'] +extensions = ['sphinx.ext.autodoc', #'sphinx.ext.autosummary', + 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', 'sphinx.ext.coverage', + 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode'] autodoc_default_flags = [ "special-members" ] +autosummary_generate = True + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] -epydoc_mapping = { - '/_static/api/': [r'rdflib\.'], - } +#epydoc_mapping = { +# '/_static/api/': [r'rdflib\.'], +# } # The suffix of source filenames. diff --git a/docs/gettingstarted.rst b/docs/gettingstarted.rst index 7fa6dd47..7b4e9825 100644 --- a/docs/gettingstarted.rst +++ b/docs/gettingstarted.rst @@ -11,7 +11,7 @@ RDFLib is open source and is maintained in a `GitHub <http://github.com/RDFLib/rdflib/>`_ repository. RDFLib releases, current and previous are listed on `PyPi <http://pypi.python.org/pypi/rdflib/>`_ -The best way to install RDFLib is to use easy_install or pip: +The best way to install RDFLib is to use ``easy_install`` or ``pip``: .. code-block :: bash @@ -42,15 +42,19 @@ A tiny usage example: .. code-block:: pycon - >>> import rdflib - >>> g = rdflib.Graph() - >>> result = g.parse("http://www.w3.org/People/Berners-Lee/card") - >>> print("graph has %s statements." % len(g)) - graph has 79 statements. - >>> for subj, pred, obj in g: - ... if (subj, pred, obj) not in g: - ... raise Exception("It better be!") - >>> s = g.serialize(format='n3') + import rdflib + + g = rdflib.Graph() + result = g.parse("http://www.w3.org/People/Berners-Lee/card") + + print("graph has %s statements." % len(g)) + # prints graph has 79 statements. + + for subj, pred, obj in g: + if (subj, pred, obj) not in g: + raise Exception("It better be!") + + s = g.serialize(format='n3') A more extensive example: @@ -62,17 +66,14 @@ A more extensive example: g = Graph() - # Bind a few prefix, namespace pairs. - g.bind("dc", DC) - g.bind("foaf", FOAF) - # Create an identifier to use as the subject for Donna. donna = BNode() # Add triples using store's add method. - g.add((donna, RDF.type, FOAF["Person"])) - g.add((donna, FOAF["nick"], Literal("donna", lang="foo"))) - g.add((donna, FOAF["name"], Literal("Donna Fales"))) + g.add( (donna, RDF.type, FOAF.Person]) ) + g.add( (donna, FOAF.nick, Literal("donna", lang="foo")) ) + g.add( (donna, FOAF.name, Literal("Donna Fales")) ) + g.add( (donna, FOAF.mbox, URIRef("mailto:donna@example.org")) ) # Iterate over triples in store and print them out. print("--- printing raw triples ---") @@ -81,8 +82,14 @@ A more extensive example: # For each foaf:Person in the store print out its mbox property. print("--- printing mboxes ---") - for person in g.subjects(RDF.type, FOAF["Person"]): - for mbox in g.objects(person, FOAF["mbox"]): + for person in g.subjects(RDF.type, FOAF.Person): + for mbox in g.objects(person, FOAF.mbox): print(mbox) -Many more :mod:`examples` can be found in the :file:`examples` folder in the source distribution. + # Bind a few prefix, namespace pairs for more readable output + g.bind("dc", DC) + g.bind("foaf", FOAF) + + print( g.serialize(format='n3') ) + +Many more :doc:`apidocs/examples` can be found in the :file:`examples` folder in the source distribution. diff --git a/docs/graphs_bnodes.rst b/docs/graphs_bnodes.rst deleted file mode 100644 index 03c5815d..00000000 --- a/docs/graphs_bnodes.rst +++ /dev/null @@ -1,468 +0,0 @@ -.. _graphs_bnodes: - -==================================== -Graphs, Named Graphs and Blank Nodes -==================================== - -Vin's question -============== - -Clarifying the query more precisely: - -.. code-block:: pycon - - >>> from rdflib import Graph, ConjunctiveGraph, URIRef - -[1] - -.. code-block:: pycon - - >>> graph = Graph('MySQL', identifier = URIRef('http://www.example.com')) - >>> graph.identifier - rdflib.URIRef('http://www.example.com') - -[2] - -.. code-block:: pycon - - >>> graph1 = ConjunctiveGraph('MySQL', identifier = URIRef('http://www.example.com')) - >>> graph1.identifier - rdflib.BNode('VLjQILCh3') - -[3] - -.. code-block:: pycon - - >>> graph1 = ConjunctiveGraph('MySQL', identifier = URIRef('http://www.example.com')) - >>> graph1.identifier - rdflib.BNode('VLjQILCh4') - -In [1] when I mention the Graph identifier, the return is a persistent -URIRef (i.e. it can be used out of the current model as well) which -gives me a unique name for the graph and now I am free to use it in -other model as well - maybe it can be used for merging graphs. - -Whereas in [2] and [3], when I mention Graph identifier the return is a -BNode which changes value every time we invoke it (and hence BNodes -have local scope and are not good for using outside the model). - -My query was simply to know why the Model "identifier" is giving BNode in -[2] comparing to a persistent URI in case [1]? In ConjunctiveGraph, -identifier is inherited from the Graph class. - -The discourse -============= - -This sparql-dev discussion airs some of the issues ... - -0016: Nuutti Kotivuori ----------------------- -http://lists.w3.org/Archives/Public/public-sparql-dev/2006JulSep/0016.html - -This isn't exactly a SPARQL question, but it is very closely -related. I will first outline the question context. - -Assume an RDF statement store, which has a mechanism for tracking -statement origin (scope, context, graph, source whatever). Many of the -statements have a distinct origin, or source graph, they were imported -from. But there are also those which either seemingly have no origin, -or the origin is not known. The origin of these statements have to be -handled somehow. We'll come to the specific choices later on. - -This statement store offers a SPARQL query interface into it. The -facilities for querying named graphs in SPARQL would obviously be used -to query the different origins in the store. But there are two things -to decide. First, how should statements without an origin be accessed -in SPARQL? There are several choices on this, which I will outline -below. And related to the first one, second, what should the default -graph be for the queries if none is given explicitly. - -I will list a few possibilities and mention the problems and benefits -that seem to result from them as a basis for discussion. - - 1. Unknown origin is a distinct node, but separate from all uris, - blank nodes or literals. The default graph for the query is the - graph of the unknown origin nodes. - - - Separation of identifier spaces, no fear of any overlap. The - graph of statements with unknown origin is separate from any - named graph. - - - Since there is no way to represent the unknown origin in SPARQL - syntax, the default graph is the only way to access the nodes in - that graph. - - - The nodes in the unknown origin graph are not matched by any - graph query, since the name of the graph could not be returned - reasonably. That is: - - .. code-block:: text - - SELECT ?g ?s ?o ?p - WHERE { GRAPH ?g { ?s ?p ?o } } - - cannot return ?g for the unknown origin graph. - - 2. Unknown origin is a distinct node, as above. The default graph is - the RDF merge of all graphs in the store, including the statements - with an unknown origin. - - - The problems above. - - - In addition, there is no way to select nodes that explicitly - have an unknown origin. (Or is there? Could one match all the - statements for which there is no graph with the same statement? - In any case, this would be quite contorted.) - - 3. Unknown origin is represented by a distinct blank node; that is, - every statement has it's own blank node as the graph name, which - is not shared with any of the other statements. The default graph - is the RDF merge of all graphs in the store, including the - statements with an unknown origin. - - - This is probably closest to accurate modelling of the - situation. We know every statement has an origin, we just don't - know what it is - a situation commonly modelled with a blank - node. Also, we don't know which statements might share an - origin, so until we know better, we make them all distinct. - - - The origin of the statements is nicely queryable with SPARQL - queries and every statement has an origin, even if unknown. - - - Queries which specify several statements from a single graph - will not match the statements with unknown origins as it cannot - be confirmed that they would be from the same graph. - - - There is no way to match the origin of a single statement as - there is no way to match a certain blank node explicitly. The - current SPARQL treats it as an open variable(?). - - - There is no way to explicitly match statements that have an - unknown origin, since the origins are just distinct blank nodes. - - - Possibly hard to implement, because of the number of distinct - blank nodes. - - 4. Unknown origin is represented by a singleton blank node; that is, - every statement with an unknown origin shares one single blank - node as the graph name. The default graph is the RDF merge of all - graphs in the store. - - - Lumps all statements with an unknown origin under a single named - graph. Queries which match several statements from a single - graph will match statement sets from unknown origin as well. - - - The origin of the statements is nicely queryable with SPARQL - queries and every statement has an origin, even if unknown. - - - There is no way to explicitly match statements that have an - unknown origin, since the origin is a single blank node. If the - application provided a magic type for this blank node (_:x a - rdfx:UnknownOrigin), this could be matched with: - - .. code-block:: text - - SELECT ?s ?o ?p - WHERE { ?g a rdfx:UnknownOrigin . - GRAPH ?g { ?s ?o ?p } } - - But this again is quite contorted. (The same could be applied to - the third case as well, but the implementation of that would be - really tricky to be effecient.) - - 5. Unknown origin is represented by a singleton blank node as - above. The default graph is the singleton blank node of unknown - origin. - - - Mostly as above, but in the common case, explictly matching - statements that have an unknown origin would be easy in just - matching the statements from the default graph. - - 6. Unknown origin is represented by a well known URI that is shared - universally. The default graph is the RDF merge of all graphs in - the store. - - - Somewhat incorrectly asserts that the statements have a certain - origin, even though we don't know the origin. - - - The origin of the statements is nicely queryable with SPARQL. - - - Statements with an unknown origin can be easily explicitly - matched by comparing them against the well known URI. - - - Assigns a special meaning to an URI. - - - Hard to coordinate with a number of people implementing similar - solutions if not standardized. - -Some other variants of the above were omitted, since their problems -and benefits are easily reasoned. - -On irc, 'chimenzie' outlined the problem as such: - -17:35 chimezie:#swig => Hmm.. well, seems like what is missing is a good - definition of a 'name for nodes that don't have an explicit context' -17:36 chimezie:#swig => or rather 'a name for the context of nodes that aren't - assigned to a context explicitely' - -So, I'm out for some input on what might be the sanest route to -through this. - -TIA, --- Naked - -0018: Richard Cyganiak ----------------------- - -http://lists.w3.org/Archives/Public/public-sparql-dev/2006JulSep/0018.html - -Hi Nuutti, - -Without having thought through all the consequences ... - -Some of your options are not really possible with named graphs -because graphs need to be *named*, that is, the name *must* be a URI -and not a blank node. Blank nodes are always scoped to a single -graph, and using blank nodes as graph labels would make it impossible -to refer to a named graph from the outside world. This excludes #3 -and #4. - -In SPARQL, the default graph is structurally and syntactically -handled so differently from the other graphs that I wouldn't consider -using it for the same kind of data. That is, I tend to reserve the -default graph for metadata or the merge of all named graphs. This -excludes #1 and #5. - -#6 has the problem of re-using a single URI for many different things --- the statements of unknown origin in Alice's store, *and* the -statements of unknown origin in Bob's store. While workable, this is -not an elegant solution. - -I would suggest that Alice and Bob each mint a new URI for the graph -containing the statements of unknown origin *in their own store*. Or -mint a new URI to hold each individual statement, or anything in -between. Since the owner of a URI gets to say what the meaning of the -URI is, they can declare that this chunk of URI space is reserved for -this purpose (assuming Alice and Bob each own a chunk of URI space). - -I wonder why you discounted this solution? - -I also question the existence of "statements without a known origin". -They surely didn't just pop up magically inside your triple store, -eh? I guess it's more like "statements whose origin I don't want to -model". - - -0020: Chimezie Ogbuji ---------------------- - -http://lists.w3.org/Archives/Public/public-sparql-dev/2006JulSep/0020.html - -On Wed, 13 Sep 2006, Richard Cyganiak wrote: - -.. code-block:: text - - > Hi Nuutti, - > - > Without having thought through all the consequences ... - > - > Some of your options are not really possible with named graphs because graphs - > need to be *named*, that is, the name *must* be a URI and not a blank node. - -I don't agree. What's the source of this assertion? I think the core -issue here is that there is *no* concensus formalism for named graphs WRT RDF, yet SPARQL is dependent -on an RDF model that supports named graphs. If there is one, please -point me to it, because I ran across the same problem when constructing -programming APIs for named graphs. The only formalism I know of is Graham Kyle, John McCarthy's work [1]. - -.. code-block:: text - - > Blank nodes are always scoped to a single graph, and using blank nodes as - > graph labels would make it impossible to refer to a named graph from the - > outside world. This excludes #3 and #4. - -Well, Blank nodes used within a graph can't be referred to -directly but they can still be matched by SPARQL - doesn't make them any -less useful. The problem isn't the use of Blank nodes for graph names but -a the lack of a mechanism [2] to match the graph name(s) associated with a -node. Given how closely coupled SPARQL is with (admittedly informal) -named graph semantics, I would expect to be able to answer questions such as: - -"What are the graph names in which all the statements about <someIRI> are -asserted?" - -Assuming I could answer this question, then graph labels that are blank -nodes become as accessible as blank nodes asserted *within* a graph and it -becomes a question of what is the appropriate use for a bnode as a graph -label? - -If BNodes are used for existential assertions about nodes, why wouldn't -they be used as existential assertions about graphs? And if there is -some semantic consequence, it furthers the argument that the formalisms -for named graphs should be well articulated before they are tightly integrated into a query language. - -.. code-block:: text - - > I would suggest that Alice and Bob each mint a new URI for the graph - > containing the statements of unknown origin *in their own store*. Or mint a - > new URI to hold each individual statement, or anything in between. Since the - > owner of a URI gets to say what the meaning of the URI is, they can declare - > that this chunk of URI space is reserved for this purpose (assuming Alice and - > Bob each own a chunk of URI space). - > - > I wonder why you discounted this solution? - -I don't think it's an elegant solution when we already have the means -(within 'vanilla' RDF Model Theory) to express -existential assertions - which is exactly the scenario here. - -If a graph label is nothing but a name associated with a set of graphs, -why should it not behave the same as the name associated with a node -within a graph? - -.. code-block:: text - - > I also question the existence of "statements without a known origin". They - > surely didn't just pop up magically inside your triple store, eh? I guess - > it's more like "statements whose origin I don't want to model". - -How different is this from "nodes whose names I don't care to maintain / -model?" - -[1] http://ninebynine.org/RDFNotes/UsingContextsWithRDF.html#xtocid-6303976 - -[2] http://copia.ogbuji.net/blog/2006-07-14/querying-named-rdf-graph-aggregate - -0023: Nuutti Kotivuori ----------------------- - -http://lists.w3.org/Archives/Public/public-sparql-dev/2006JulSep/0023.html - -Chimezie Ogbuji wrote: - -.. code-block:: text - - > I don't agree. What's the source of this assertion? I think the - > core issue here is that there is *no* concensus formalism for named - > graphs WRT RDF, yet SPARQL is dependent on an RDF model that - > supports named graphs. If there is one, please point me to it, - > because I ran across the same problem when constructing programming - > APIs for named graphs. The only formalism I know of is Graham Kyle, - > John McCarthy's work [1]. - -Well, one thing which would help me in this is a survey of the -approaches other people have taken when doing these things. - -I think I know the situation with Redland librdf, when I read the code -last, but I'm not sure if I'm correct. - -I think that in librdf, there are statements explicitly without a -context. In SPARQL queries, the default graph is the merge of all -statements in the store, with or without a context. Queries which -explicitly match the graph in a variable never match statements -without a context. And so there is no easy way to match all the -statements without a context only. - -I'd like to know atleast how rdflib and Jena (with whatever extensions -that this requires) solve this issue. - --- Naked - -0027: Chimezie Ogbuji ---------------------- - -http://lists.w3.org/Archives/Public/public-sparql-dev/2006JulSep/0027.html - -RDFLib has two API's: a Store API and a Graph API. Every Graph (there -are several kinds: QuotedGraphs, ConjunctiveGraphs, Named Graphs, -AggregateGraphs, ..) is associated with a Store instance and an -identifier. The identifiers are either a Blank Node or a URI. - -All the Store API's take a fourth parameter which is the containing Graph -(even the :meth:`__len__` method). So, theoretically the Store can choose to -persist RDF triples in a flat space (i.e., vanilla RDF model) and disregard the fourth parameter or use -the identifier of the containing graph to partition its persistence space -accordingly - it can even choose to partition formulae seperately (to -support N3 persistence) from the kind of Graph passed down to it (it will -receive QuotedGraph instances as the fourth parameter in this case). - -The :meth:`Store.triples` method returns a generator of (s,p,o), graphInst so each -Store implementation is expected to be able to associate each triple with -a containing graph (or None if the Store chooses to persist triples in a -flat space). - -The Graph API's do most of the leg work of named graph aggregation. - - -:class:`ReadOnlyGraphAggregate` is a subset of the :class:`ConjunctiveGraph` where the names -of the graphs it provides an aggregate view for are passed on in the -constructor - this is how a SPARQL query with multiple FROM NAMED is -supported. - -:class:`QuotedGraphs` are meant to implement Notation 3 formulae. They are -associated with a required identifier that the N3 parser must provide in -order to maintain consistent formulae identification for scenarios such as -implication and such. - -The default dataset for SPARQL queries is equivalent to the Graph instance -on which the query is dispatched. If the :meth:`query` method is called on a -:class:`ConjunctiveGraph`, the default dataset is the entire Store, if it's a named -graph it's the named graph. - -This setup supports: - -- Flat space of triples -- Named Graph partitioning -- Notation 3 persistence - -0028: Nuutti Kotivuori ----------------------- - -http://lists.w3.org/Archives/Public/public-sparql-dev/2006JulSep/0028.html - -Chimezie Ogbuji wrote: - -.. code-block:: text - - > The Graph API's do most of the leg work of named graph - > aggregation. ConjunctiveGraph is an (unamed) aggregation of all the - > named graphs within the Store. It has a 'default' graph, whose name - > is associated with the ConjunctiveGraph throughout it's life. All - > methods work against this default graph. Its constructor can take an - > identifier to use as the name of this 'default' graph or it will - > assign a BNode. In practice (at least how *I* use RDFLib), I - > instanciate a ConjunctiveGraph if I want to add triples to the Store - > but don't care to mint a URI for the graph (the scenario which - > triggered this thread). These triples can still be addressed. - -Okay, in the context of this discussion, what RDFLib does is that -every time a ConjunctiveGraph is instantiated, it creates a new blank -node and uses that throughout the life of the ConjunctiveGraph -object. And the default graph is the merge of all graphs in the store. - -So triples without an origin will be associated with a blank node, -which is shared between added triples, but distinct between different -ConjunctiveGraph objects. This probably coincides rather nicely with -most usages of the API. Single "sessions" of manipulating nodes will -have the blank node origin shared. - -And the possible problems are mostly what was already mentioned -earlier about an approach like this. The blank node identities might -not coincide with the actual separateness of the sources graphs - -making a query which matches several statements out of a single graph -might not be too meaningful for these blank nodes. It is difficult to -query only nodes which have no specific origin. And since the graph -name is a blank node, there is no way to explicitly specify the graph -name to be specific blank node, as the SPARQL syntax doesn't allow -this. - --- Naked - -References ----------- - -Two posts by Pat Hayes, recommended by Andy Seaborne. - -http://www.ihmc.us/users/phayes/RDFGraphSyntax.html - -http://lists.w3.org/Archives/Public/public-rdf-dawg/2006JulSep/0153.html diff --git a/docs/index.rst b/docs/index.rst index 44cc13f7..0eea1b2d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -31,7 +31,7 @@ If you never used RDFLib, click through these intro_to_graphs intro_to_sparql - RDFLib Examples <apidocs/examples> + RDFLib examples <apidocs/examples> In depth -------- diff --git a/docs/intro_to_creating_rdf.rst b/docs/intro_to_creating_rdf.rst index 7d72f540..abad6526 100644 --- a/docs/intro_to_creating_rdf.rst +++ b/docs/intro_to_creating_rdf.rst @@ -15,32 +15,36 @@ A ``BNode`` is a node where the exact URI is not known. Nodes can be created by the constructors of the node classes:: - >>> from rdflib import URIRef, BNode, Literal - >>> bob = URIRef("http://example.org/people/Bob") - >>> linda = BNode() # a GUID is generated - >>> name = Literal('Bob') # passing a string - >>> age = Literal(24) # passing a python int - >>> height = Literal(76.5) # passing a python float + from rdflib import URIRef, BNode, Literal -Literals can be created from python objects, these created ``data-typed literals``, for the details on the mapping see :ref:`literals`. + bob = URIRef("http://example.org/people/Bob") + linda = BNode() # a GUID is generated + + name = Literal('Bob') # passing a string + age = Literal(24) # passing a python int + height = Literal(76.5) # passing a python float + +Literals can be created from python objects, this creates ``data-typed literals``, for the details on the mapping see :ref:`rdflibliterals`. For creating many ``URIRefs`` in the same ``namespace``, i.e. URIs with the same prefix, RDFLib has the :class:`rdflib.namespace.Namespace` class:: - >>> from rdflib import Namespace - >>> n = Namespace("http://example.org/people/") - >>> n.bob - rdflib.term.URIRef(u'http://example.org/people/bob') - >>> n.eve - rdflib.term.URIRef(u'http://example.org/people/eve') + from rdflib import Namespace + + n = Namespace("http://example.org/people/") + + n.bob # = rdflib.term.URIRef(u'http://example.org/people/bob') + n.eve # = rdflib.term.URIRef(u'http://example.org/people/eve') This is very useful for schemas where all properties and classes have the same URI prefix, RDFLib pre-defines Namespaces for the most common RDF schemas:: - >>> from rdflib.namespace import RDF, FOAF - >>> RDF.type - rdflib.term.URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') - >>> FOAF.knows - rdflib.term.URIRef(u'http://xmlns.com/foaf/0.1/knows') + from rdflib.namespace import RDF, FOAF + + RDF.type + # = rdflib.term.URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') + + FOAF.knows + # = rdflib.term.URIRef(u'http://xmlns.com/foaf/0.1/knows') Adding Triples -------------- @@ -54,16 +58,16 @@ Triples can also be added with the :meth:`~rdflib.graph.Graph.add` function: :meth:`~rdflib.graph.Graph.add` takes a 3-tuple of RDFLib nodes. Try the following with the nodes and namespaces we defined previously:: - >>> from rdflib import Graph - >>> g = Graph() + from rdflib import Graph + g = Graph() - >>> g.add( (bob, RDF.type, FOAF.Person) ) - >>> g.add( (bob, FOAF.name, name) ) - >>> g.add( (bob, FOAF.knows, linda) ) - >>> g.add( (linda, RDF.type, FOAF.Person) ) - >>> g.add( (linda, FOAF.name, Literal('Linda') ) ) + g.add( (bob, RDF.type, FOAF.Person) ) + g.add( (bob, FOAF.name, name) ) + g.add( (bob, FOAF.knows, linda) ) + g.add( (linda, RDF.type, FOAF.Person) ) + g.add( (linda, FOAF.name, Literal('Linda') ) ) - >>> print g.serialize(format='turtle') + print g.serialize(format='turtle') outputs: @@ -79,17 +83,21 @@ outputs: foaf:name "Linda" ] ; foaf:name "Bob" . -For some properties, only one value per resource makes sense (i.e they are *functional properties*, or have max-cardinality of 1). The :meth:`~rdflib.graph.Graph.set` method is useful for this:: +For some properties, only one value per resource makes sense (i.e they are *functional properties*, or have max-cardinality of 1). The :meth:`~rdflib.graph.Graph.set` method is useful for this: - >>> g.add( ( bob, FOAF.age, Literal(42) ) - >>> print "Bob is ", g.value( bob, FOAF.age ) - Bob is 42 +.. code-block:: python + + g.add( ( bob, FOAF.age, Literal(42) ) + print "Bob is ", g.value( bob, FOAF.age ) + # prints: Bob is 42 - >>> g.set( ( bob, age, Literal(43) ) ) # replaces 42 set above - >>> print "Bob is now ", g.value( bob, FOAF.age ) - Bob is now 43 + g.set( ( bob, age, Literal(43) ) ) # replaces 42 set above + print "Bob is now ", g.value( bob, FOAF.age ) + # prints: Bob is now 43 + +:meth:`rdflib.graph.Graph.value` is the matching query method, it will return a single value for a property, optionally raising an exception if there are more. -(:meth:`rdflib.graph.Graph.value` is the matching query method, it will return a single value for a property, optionally raising an exception if there are more.) +You can also add triples by combining entire graphs, see :ref:`graph-setops`. Removing Triples ^^^^^^^^^^^^^^^^ @@ -101,5 +109,20 @@ Similarly, triples can be removed by a call to :meth:`~rdflib.graph.Graph.remove When removing, it is possible to leave parts of the triple unspecified (i.e. passing ``None``), this will remove all matching triples:: - >>> g.remove( (bob, None, None) ) # remove all triples about bob + g.remove( (bob, None, None) ) # remove all triples about bob + +An example +^^^^^^^^^^ + +LiveJournal produces FOAF data for their users, but they seem to use +``foaf:member_name`` for a person's full name. To align with data from +other sources, it would be nice to have ``foaf:name`` act as a synonym +for ``foaf:member_name`` (a poor man's one-way +``owl:equivalentProperty``): + +.. code-block:: python + from rdflib.namespace import FOAF + g.parse("http://danbri.livejournal.com/data/foaf") + for s,_,n: in g.triples((None, FOAF['member_name'], None)): + g.add((s, FOAF['name'], n)) diff --git a/docs/intro_to_graphs.rst b/docs/intro_to_graphs.rst index eabd55a3..7d4b68d6 100644 --- a/docs/intro_to_graphs.rst +++ b/docs/intro_to_graphs.rst @@ -4,7 +4,7 @@ Navigating Graphs ================= -An RDF Graph is a set of RDF triples, and we try to mirror exactly this in RDFLib, and the graph tries to emulate a container type. +An RDF Graph is a set of RDF triples, and we try to mirror exactly this in RDFLib, and the graph tries to emulate a container type: Graphs as Iterators ------------------- @@ -13,28 +13,75 @@ RDFLib graphs override :meth:`~rdflib.graph.Graph.__iter__` in order to support .. code-block:: python - for subject,predicate,obj_ in someGraph: - assert (subject,predicate,obj_) in someGraph, "Iterator / Container Protocols are Broken!!" + for subject,predicate,obj in someGraph: + if not (subject,predicate,obj) in someGraph: + raise Exception("Iterator / Container Protocols are Broken!!") + +Contains check +-------------- + +Graphs implement :meth:`~rdflib.graph.Graph.__contains__`, so you can check if a triple is in a graph with ``triple in graph`` syntax:: + + from rdflib import URIRef + from rdflib.namespace import RDF + bob = URIRef("http://example.org/people/bob") + if ( bob, RDF.type, FOAF.Person ) in graph: + print "This graph knows that Bob is a person!" + +Note that this triple does not have to be completely bound:: + + if (bob, None, None) in graph: + print "This graph contains triples about Bob!" + +.. _graph-setops: Set Operations on RDFLib Graphs ------------------------------- -:meth:`~rdflib.graph.Graph.__iadd__` and :meth:`~rdflib.graph.Graph.__isub__` are overridden to support adding and subtracting Graphs to/from each other (in place): +Graphs override several pythons operators: :meth:`~rdflib.graph.Graph.__iadd__`, :meth:`~rdflib.graph.Graph.__isub__`, etc. This supports addition, subtraction and other set-operations on Graphs: -* G1 += G1 -* G2 -= G2 +============ ================================================== +operation effect +============ ================================================== +``G1 + G2`` return new graph with union +``G1 += G1`` in place union / addition +``G1 - G2`` return new graph with difference +``G1 -= G2`` in place difference / subtraction +``G1 & G2`` intersection (triples in both graphs) +``G1 ^ G2`` xor (triples in either G1 or G2, but not in both) +============ ================================================== -.. warning: If you are using blank-nodes set-operations on graphs may or may not do what you want, +.. warning:: Set-operations on graphs assume bnodes are shared between graphs. This may or may not do what you want. Basic Triple Matching --------------------- -RDFLib graphs support basic triple pattern matching with a :meth:`~rdflib.graph.Graph.triples` function. +Instead of iterating through all triples, RDFLib graphs support basic triple pattern matching with a :meth:`~rdflib.graph.Graph.triples` function. +This function is a generator of triples that match the pattern given by the arguments. The arguments of these are RDF terms that restrict the triples that are returned. Terms that are :data:`None` are treated as a wildcard. For example:: -.. automethod:: rdflib.graph.Graph.triples - :noindex: -This function is a generator of triples that match the pattern given by the arguments. The arguments of these are RDF terms that restrict the triples that are returned. Terms that are :data:`None` are treated as a wildcard. + g.load("some_foaf.rdf") + for s,p,o in g.triples( (None, RDF.type, FOAF.Person) ): + print "%s is a person"%o + + for s,p,o in g.triples( (None, RDF.type, None) ): + print "%s is a %s"%(s,o) + + bobgraph = Graph() + + bobgraph += g.triples( (bob, None, None) ) + +If you are not interested in whole triples, you can get only the bits you want with the methods :meth:`~rdflib.graph.Graph.objects`, :meth:`~rdflib.graph.Graph.subjects`, :meth:`~rdflib.graph.Graph.predicates`, :meth:`~rdflib.graph.Graph.predicates_objects`, etc. Each take parameters for the components of the triple to constraint:: + + for person in g.subject(RDF.type, FOAF.Person): + print "%s is a person"%person + + +Finally, for some properties, only one value per resource makes sense (i.e they are *functional properties*, or have max-cardinality of 1). The :meth:`~rdflib.graph.Graph.value` method is useful for this, as it returns just a single node, not a generator:: + + name = g.value(bob, FOAF.name) # get any name of bob + # get the one person that knows bob and raise an exception if more are found + mbox = g.value(predicate = FOAF.name, object = bob, any = False) @@ -43,16 +90,12 @@ This function is a generator of triples that match the pattern given by the argu :class:`~rdflib.graph.Graph` methods for accessing triples ----------------------------------------------------------- -.. automethod:: rdflib.graph.Graph.add - :noindex: -.. automethod:: rdflib.graph.Graph.set - :noindex: +Here is a list of all convenience methods for querying Graphs: + .. automethod:: rdflib.graph.Graph.label :noindex: .. automethod:: rdflib.graph.Graph.preferredLabel :noindex: -.. automethod:: rdflib.graph.Graph.remove - :noindex: .. automethod:: rdflib.graph.Graph.triples :noindex: .. automethod:: rdflib.graph.Graph.value diff --git a/docs/intro_to_parsing.rst b/docs/intro_to_parsing.rst index 7a585aee..f4d08bf3 100644 --- a/docs/intro_to_parsing.rst +++ b/docs/intro_to_parsing.rst @@ -17,20 +17,20 @@ RDF data has various syntaxes (``xml``, ``n3``, ``ntriples``, ``trix``, etc) tha You need to tell RDFLib what format to parse, use the ``format`` keyword-parameter to :meth:`~rdflib.graph.Graph.parse`, you can pass either a mime-type or the name (a :doc:`list of available parsers <plugin_parsers>` is available). If you are not sure what format your file will be, you can use :func:`rdflib.util.guess_format` which will guess based on the file extension. -In an interactive python interpreter, try this: - -.. code-block:: pycon - - >>> from rdflib import Graph - >>> g = Graph() - >>> g.parse("demo.nt", format="nt") - <Graph identifier=HCbubHJy0 (<class 'rdflib.graph.Graph'>)> - >>> len(g) - 2 - >>> import pprint - >>> for stmt in g: - ... pprint.pprint(stmt) - ... +In an interactive python interpreter, try this:: + + from rdflib import Graph + + g = Graph() + g.parse("demo.nt", format="nt") + + len(g) # prints 2 + + import pprint + for stmt in g: + pprint.pprint(stmt) + + # prints : (rdflib.term.URIRef('http://bigasterisk.com/foaf.rdf#drewp'), rdflib.term.URIRef('http://example.com/says'), rdflib.term.Literal(u'Hello world')) @@ -43,13 +43,11 @@ The final lines show how RDFLib represents the two statements in the file. The s Reading remote graphs --------------------- -Reading graphs from the net is just as easy: - -.. code-block:: pycon +Reading graphs from the net is just as easy:: - >>> g.parse("http://bigasterisk.com/foaf.rdf") - >>> len(g) - 42 + g.parse("http://bigasterisk.com/foaf.rdf") + len(g) + # prints 42 The format defaults to ``xml``, which is the common format for .rdf files you'll find on the net. diff --git a/docs/intro_to_sparql.rst b/docs/intro_to_sparql.rst index b096b409..d46f292a 100644 --- a/docs/intro_to_sparql.rst +++ b/docs/intro_to_sparql.rst @@ -4,26 +4,6 @@ Querying with SPARQL ==================== -Create an Rdflib Graph -^^^^^^^^^^^^^^^^^^^^^^ - -You might parse some files into a new graph (see :doc:`Introduction to parsing <intro_to_parsing>`) or open an on-disk rdflib store. - -.. code-block:: python - - from rdflib import Graph - g = Graph() - g.parse("http://bigasterisk.com/foaf.rdf") - g.parse("http://www.w3.org/People/Berners-Lee/card.rdf") - -LiveJournal produces FOAF data for their users, but they seem to use ``foaf:member_name`` for a person's full name. For this demo, I made ``foaf:name`` act as a synonym for ``foaf:member_name`` (a poor man's one-way ``owl:equivalentProperty``): - -.. code-block:: python - - from rdflib.namespace import FOAF - g.parse("http://danbri.livejournal.com/data/foaf") - for s,_,n: in g.triples((None, FOAF['member_name'], None)): - g.add((s, FOAF['name'], n)) Run a Query ^^^^^^^^^^^ @@ -40,6 +20,11 @@ Continuing the example... import rdflib + g = rdflib.Graph() + + # ... add some triples to g somehow ... + g.parse("some_foaf_file.rdf") + qres = g.query( """SELECT DISTINCT ?aname ?bname WHERE { diff --git a/docs/namespaces_and_bindings.rst b/docs/namespaces_and_bindings.rst index b0d243f2..151e4e67 100644 --- a/docs/namespaces_and_bindings.rst +++ b/docs/namespaces_and_bindings.rst @@ -6,38 +6,36 @@ 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: +The :mod:`rdflib.namespace` defines the :class:`rdflib.namespace.Namespace` class which lets you easily create URIs in a namespace:: -.. code-block:: python + from rdflib import Namespace - >>> from rdflib import Namespace - >>> n = Namespace("http://example.org/") - >>> n.Person # as attribute - rdflib.term.URIRef(u'http://example.org/Person') - >>> n['first%20name'] # as item - for things that are not valid python identifiers - rdflib.term.URIRef(u'http://example.org/first%20name') + n = Namespace("http://example.org/") + n.Person # as attribute + # = rdflib.term.URIRef(u'http://example.org/Person') + + n['first%20name'] # as item - for things that are not valid python identifiers + # = rdflib.term.URIRef(u'http://example.org/first%20name') The ``namespace`` module also defines many common namespaces such as RDF, RDFS, OWL, FOAF, SKOS, etc. -Namespaces can also be associated with prefixes, in a :class:`rdflib.namespace.NamespaceManager`, i.e. 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. Additional prefixes can be bound with the :meth:`rdflib.graph.bind` method. +Namespaces can also be associated with prefixes, in a :class:`rdflib.namespace.NamespaceManager`, i.e. 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. Additional prefixes can be bound with the :meth:`rdflib.graph.bind` method. 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. - -.. code-block:: python +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 }) + ... + 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:: text +.. code-block:: sparql PREFIX : <http://xmlns.com/foaf/0.1/> diff --git a/docs/rdf_terms.rst b/docs/rdf_terms.rst index 5fe883d5..526c6327 100644 --- a/docs/rdf_terms.rst +++ b/docs/rdf_terms.rst @@ -64,7 +64,8 @@ URIRefs u'<http://example.com>' -.. literals: +.. _rdflibliterals: + Literals ======== |
