<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns="http://purl.org/rss/1.0/">
  <channel rdf:about="http://blog.datagraph.org/index.rss">
    <title>The Datagraph Blog</title>
    <link>http://blog.datagraph.org/</link>
    <description>The official Datagraph.org blog.</description>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="http://blog.datagraph.org/2010/12/rdf-for-ruby"/>
        <rdf:li rdf:resource="http://blog.datagraph.org/2010/05/spira"/>
        <rdf:li rdf:resource="http://blog.datagraph.org/2010/04/rdf-nosql-diff"/>
        <rdf:li rdf:resource="http://blog.datagraph.org/2010/04/parsing-rdf-with-ruby"/>
        <rdf:li rdf:resource="http://blog.datagraph.org/2010/04/rdf-repository-howto"/>
        <rdf:li rdf:resource="http://blog.datagraph.org/2010/04/transmuting-ntriples"/>
        <rdf:li rdf:resource="http://blog.datagraph.org/2010/03/rdf-isomorphism"/>
        <rdf:li rdf:resource="http://blog.datagraph.org/2010/03/rdf-for-ruby"/>
        <rdf:li rdf:resource="http://blog.datagraph.org/2010/03/grepping-ntriples"/>
        <rdf:li rdf:resource="http://blog.datagraph.org/2010/02/hacking-rdf-in-ruby"/>
        <rdf:li rdf:resource="http://blog.datagraph.org/2010/02/jquery-with-rails-3"/>
        <rdf:li rdf:resource="http://blog.datagraph.org/2009/11/sparql-1.1-critique"/>
      </rdf:Seq>
    </items>
    <sy:updatePeriod>weekly</sy:updatePeriod>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </channel>
  <item rdf:about="http://blog.datagraph.org/2010/12/rdf-for-ruby">
    <title>What's New in RDF.rb 0.3.0</title>
    <link>http://blog.datagraph.org/2010/12/rdf-for-ruby</link>
    <description>
&lt;p&gt;It has now been nine months since the &lt;a href="http://blog.datagraph.org/2010/03/rdf-for-ruby"&gt;initial public release&lt;/a&gt; of &lt;a href="http://rdf.rubyforge.org/"&gt;RDF.rb&lt;/a&gt;, our &lt;a href="http://www.w3.org/RDF/"&gt;RDF&lt;/a&gt; library for &lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt;, and today we're happy to announce the release of RDF.rb 0.3.0, a significant milestone.&lt;/p&gt;
&lt;p&gt;As the &lt;a href="https://github.com/bendiken/rdf/compare/0.2.3...0.3.0"&gt;changelog&lt;/a&gt; attests, this has been a long release cycle that incorporates 170 commits by 6 different authors. The major new features include transactions and basic graph pattern (BGP) queries, as well as the availability of robust and fast parser/serializer plugins for the RDFa, Notation3, Turtle, and RDF/XML formats, complementing other already previously supported formats. In addition, many bugs have been fixed and general improvements, including significant performance improvements, implemented.&lt;/p&gt;
&lt;p&gt;RDF.rb 0.3.0 is immediately available via &lt;a href="http://rubygems.org/"&gt;RubyGems&lt;/a&gt;, and can be installed or upgraded to as follows on any Unix box with Ruby and RubyGems:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ [sudo] gem install rdf&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In all the code examples that follow below, we will assume that RDF.rb and the built-in N-Triples parser have already been loaded up like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'rdf'
require 'rdf/ntriples'

# Enable facile references to standard vocabularies:
include RDF&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;RDFa, N3, Turtle, and RDF/XML Support&lt;/h2&gt;
&lt;p&gt;While RDF.rb 0.3.0 continues with our &lt;a href="http://blog.datagraph.org/2010/03/rdf-for-ruby"&gt;minimalist policy&lt;/a&gt; of only supporting the &lt;a href="http://blog.datagraph.org/2010/03/grepping-ntriples"&gt;N-Triples&lt;/a&gt; serialization format in the core library itself, support for every widely-used RDF serialization format is now available in the form of plugins.&lt;/p&gt;
&lt;p&gt;Thanks to the hard work of &lt;a href="http://twitter.com/gkellogg"&gt;Gregg Kellogg&lt;/a&gt;, the author of &lt;a href="https://github.com/gkellogg/rdf_context"&gt;RdfContext&lt;/a&gt;, there are now RDF.rb 0.3.0-compatible plugins available for the RDFa, Notation3, Turtle, and RDF/XML formats, complementing the already previously-available plugins for the RDF/JSON and TriX formats. See &lt;a href="http://www.kellogg-assoc.com/2010/12/27/rdf-rdfa-0-3-0"&gt;Gregg's blog post&lt;/a&gt; for more details on the particulars of these plugins.&lt;/p&gt;
&lt;p&gt;We are also pleased to announce that Gregg has joined the RDF.rb core development team, which now consists of him, &lt;a href="http://twitter.com/bhuga"&gt;Ben Lavender&lt;/a&gt;, and myself. This merger between the RDF.rb and RdfContext efforts is a perfect match, given that Ben and I have been focused more on storing and querying RDF data while Gregg has been busy single-handedly solving all RDF serialization questions.&lt;/p&gt;
&lt;p&gt;To facilitate typical &lt;a href="http://linkeddata.org/"&gt;Linked Data&lt;/a&gt; use cases, we now also provide a metadistribution of RDF.rb that includes a full set of parsing/serialization plugins; the following will install all of the &lt;code&gt;rdf&lt;/code&gt;, &lt;code&gt;rdf-isomorphic&lt;/code&gt;, &lt;code&gt;rdf-json&lt;/code&gt;, &lt;code&gt;rdf-n3&lt;/code&gt;, &lt;code&gt;rdf-rdfa&lt;/code&gt;, &lt;code&gt;rdf-rdfxml&lt;/code&gt;, and &lt;code&gt;rdf-trix&lt;/code&gt; gems in one go:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ [sudo] gem install linkeddata&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly, instead of loading up support for each RDF serialization format one at a time, you can simply use the following to load them all; this is helpful e.g. for the automatic selection of an appropriate parser plugin given a particular file name or extension:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'linkeddata'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For a tutorial introduction to RDF.rb's &lt;a href="http://rdf.rubyforge.org/RDF/Reader.html"&gt;reader&lt;/a&gt; and &lt;a href="http://rdf.rubyforge.org/RDF/Writer.html"&gt;writer&lt;/a&gt; APIs, please refer to my previous blog post &lt;a href="http://blog.datagraph.org/2010/04/parsing-rdf-with-ruby"&gt;Parsing and Serializing RDF Data with Ruby&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Query API: Basic Graph Patterns (BGPs)&lt;/h2&gt;
&lt;p&gt;The &lt;a href="http://rdf.rubyforge.org/RDF/Query.html"&gt;query API&lt;/a&gt; in RDF.rb 0.3.0 now includes &lt;a href="http://www.w3.org/TR/rdf-sparql-query/#basicpatterns"&gt;basic graph pattern&lt;/a&gt; (BGP) support, which has been a much-requested feature. BGP queries will already be a familiar concept to anyone using &lt;a href="http://en.wikipedia.org/wiki/SPARQL"&gt;SPARQL&lt;/a&gt;, and in RDF.rb they are constructed and executed like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Load some RDF.rb project information into an in-memory graph:
graph = RDF::Graph.load("http://rdf.rubyforge.org/doap.nt")

# Construct a BGP query for obtaining developers' names and e-mails:
query = RDF::Query.new({
  :person =&gt; {
    RDF.type  =&gt; FOAF.Person,
    FOAF.name =&gt; :name,
    FOAF.mbox =&gt; :email,
  }
})

# Execute the query on our in-memory graph, printing out solutions:
query.execute(graph).each do |solution|
  puts "name=#{solution.name} email=#{solution.email}"
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Executing a BGP query returns a solution sequence, encapsulated as an instance of the &lt;a href="http://rdf.rubyforge.org/RDF/Query/Solutions.html"&gt;&lt;code&gt;RDF::Query::Solutions&lt;/code&gt;&lt;/a&gt; class. Solution sequences provide a number of convenient methods for further narrowing down the returned solutions to what you're actually looking for:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Filter solutions using a hash:
solutions.filter(:author  =&gt; RDF::URI("http://ar.to/#self"))
solutions.filter(:author  =&gt; "Arto Bendiken")
solutions.filter(:updated =&gt; RDF::Literal(Date.today))

# Filter solutions using a block:
solutions.filter { |solution| solution.author.literal? }
solutions.filter { |solution| solution.title =~ /^SPARQL/ }
solutions.filter { |solution| solution.price &lt; 30.5 }
solutions.filter { |solution| solution.bound?(:date) }
solutions.filter { |solution| solution.age.datatype == XSD.integer }
solutions.filter { |solution| solution.name.language == :es }

# Reorder solutions based on a variable:
solutions.order_by(:updated)
solutions.order_by(:updated, :created)

# Select particular variables only:
solutions.select(:title)
solutions.select(:title, :description)

# Eliminate duplicate solutions:
solutions.distinct

# Limit the number of solutions:
solutions.offset(20).limit(10)

# Count the number of matching solutions:
solutions.count
solutions.count { |solution| solution.price &lt; 30.5 }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;BGP-capable storage adapters should override and implement the following &lt;a href="http://rdf.rubyforge.org/RDF/Queryable.html"&gt;&lt;code&gt;RDF::Queryable&lt;/code&gt;&lt;/a&gt; method in order to provide storage-specific optimizations for BGP query evaluation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class MyRepository &lt; RDF::Repository
  def query_execute(query, &amp;block)
    # ...
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Repository API: Transactions&lt;/h2&gt;
&lt;p&gt;The &lt;a href="http://rdf.rubyforge.org/RDF/Repository.html"&gt;repository API&lt;/a&gt; in RDF.rb 0.3.0 now includes basic transaction support:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Load some RDF.rb project information into an in-memory repository:
repository = RDF::Repository.load("http://rdf.rubyforge.org/doap.nt")

# Delete one statement and insert another, atomically:
repository.transaction do |tx|
  subject = RDF::URI('http://rubygems.org/gems/rdf')

  tx.delete [subject, DOAP.name, nil]
  tx.insert [subject, DOAP.name, "RDF.rb 0.3.0"]
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you would expect, if the transaction block raises an exception, the current transaction will be aborted and rolled back; otherwise, the transaction is automatically committed when the block returns.&lt;/p&gt;
&lt;p&gt;Transaction-capable storage adapters should override and implement the following three &lt;a href="http://rdf.rubyforge.org/RDF/Repository.html"&gt;&lt;code&gt;RDF::Repository&lt;/code&gt;&lt;/a&gt; methods:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class MyRepository &lt; RDF::Repository
  def begin_transaction(context)
    # ...
  end

  def rollback_transaction(tx)
    # ...
  end

  def commit_transaction(tx)
    # ...
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href="http://rdf.rubyforge.org/RDF/Transaction.html"&gt;&lt;code&gt;RDF::Transaction&lt;/code&gt;&lt;/a&gt; objects passed to these methods consist of a sequence of RDF statements to delete from, and a sequence of RDF statements to insert into, a given graph. The default transaction implementation in &lt;code&gt;RDF::Repository&lt;/code&gt; simply builds up a transaction object in memory, buffering all inserts/deletes until the transaction is committed, at which point the operations are then executed against the repository.&lt;/p&gt;
&lt;p&gt;Note that whether transactions are &lt;em&gt;actually&lt;/em&gt; executed atomically depends on the particulars of the storage adapter you're using. For instance, the &lt;a href="http://rdf.rubyforge.org/do/"&gt;&lt;code&gt;RDF::DataObjects&lt;/code&gt;&lt;/a&gt; plugin, which provides a storage adapter supporting SQLite, PostgreSQL, MySQL, and other RDBMS solutions, will certainly be able to offer ACID transaction support (albeit it has not been updated for that, or other 0.3.x features, just yet.)&lt;/p&gt;
&lt;p&gt;On the other hand, not e.g. all &lt;a href="http://blog.datagraph.org/2010/04/rdf-nosql-diff"&gt;NoSQL&lt;/a&gt; solutions support transactions, so storage adapters for such solutions may choose to omit explicit transaction support and have it supplied by RDF.rb's default implementation.&lt;/p&gt;
&lt;h2&gt;Performance &amp; Scalability Improvements&lt;/h2&gt;
&lt;p&gt;In earlier RDF.rb releases, our focus was strongly centered on defining the core APIs that have enabled the thriving &lt;a href="http://rubygems.org/search?query=rdf-"&gt;plugin ecosystem&lt;/a&gt; we can witness today. The focus was not so much, therefore, on the performance of the bundled default implementations of those APIs; in some cases, these implementations could have been described as being of only proof-of-concept quality.&lt;/p&gt;
&lt;p&gt;In particular, the in-memory graph and repository implementations were suboptimal in RDF.rb 0.1.x, and only somewhat improved in 0.2.x. However, reflecting the increasing production-readiness of RDF.rb in general, matters have been much improved in RDF.rb 0.3.0.&lt;/p&gt;
&lt;p&gt;Of course, performance improvements are an open-ended task, and I'm sure we'll see more work on this front in the future as need arises and time permits. But it's likely that RDF.rb 0.3.0 now offers a &lt;em&gt;sufficient&lt;/em&gt; out-of-the-box performance level for many if not most common use cases.&lt;/p&gt;
&lt;p&gt;Scalability has also been addressed by making use of &lt;a href="http://ruby-doc.org/core-1.9/classes/Enumerator.html"&gt;enumerators&lt;/a&gt; throughout the APIs defined by RDF.rb. That means that all operations are generally performed in a &lt;em&gt;streaming&lt;/em&gt; fashion, enabling you to build pipelines for hundreds of millions of RDF statements to flow through while still maintaining constant memory usage by ensuring that the statements are processed one by one.&lt;/p&gt;
&lt;h2&gt;RSpec 2.x Compatibility&lt;/h2&gt;
&lt;p&gt;Lastly, RDF.rb 0.3.0 has been upgraded to use and depend on &lt;a href="http://relishapp.com/rspec"&gt;RSpec&lt;/a&gt; 2.x instead of the previous 1.3.x branch. This requires minor changes to the &lt;code&gt;spec/spec_helper.rb&lt;/code&gt; file in any project that relies on the &lt;a href="http://rdf.rubyforge.org/spec/"&gt;&lt;code&gt;RDF::Spec&lt;/code&gt;&lt;/a&gt; library. The most minimal &lt;code&gt;spec_helper.rb&lt;/code&gt; contents are now as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'rdf/spec'

RSpec.configure do |config|
  config.include RDF::Spec::Matchers
end&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Kudos to Our Contributors&lt;/h2&gt;
&lt;p&gt;In tandem with the soon &lt;a href="http://rubygems.org/gems/rdf"&gt;10,000 downloads&lt;/a&gt; of RDF.rb on &lt;a href="http://rubygems.org/"&gt;RubyGems.org&lt;/a&gt;, a very positive sign of all the interest and ongoing work around RDF.rb is our growing contributor list. We thank everyone who has sent in bug reports, and in particular the following people who have contributed patches to RDF.rb and/or an RDF.rb plugin; in alphabetical order:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://github.com/clnx"&gt;Călin Ardelean&lt;/a&gt;, &lt;a href="http://github.com/b4d"&gt;Christoph Badura&lt;/a&gt;, &lt;a href="http://github.com/jfieber"&gt;John Fieber&lt;/a&gt;, &lt;a href="http://github.com/jgeiger"&gt;Joey Geiger&lt;/a&gt;, &lt;a href="http://github.com/jamespjh"&gt;James Hetherington&lt;/a&gt;, &lt;a href="http://github.com/cldwalker"&gt;Gabriel Horner&lt;/a&gt;, &lt;a href="http://github.com/njh"&gt;Nicholas Humfrey&lt;/a&gt;, &lt;a href="http://github.com/fumi"&gt;Fumihiro Kato&lt;/a&gt;, &lt;a href="http://github.com/drankard"&gt;David Nielsen&lt;/a&gt;, &lt;a href="http://github.com/selvan"&gt;Thamaraiselvan Poomalai&lt;/a&gt;, &lt;a href="http://github.com/ursm"&gt;Keita Urashima&lt;/a&gt;, &lt;a href="http://github.com/pius"&gt;Pius Uzamere&lt;/a&gt;, and &lt;a href="http://github.com/hellekin"&gt;Hellekin O. Wolf&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;small&gt;(My apologies if I have inadvertently omitted anyone from the previous, and please let me know about it.)&lt;/small&gt;&lt;/p&gt;
&lt;h2&gt;Looking Forward to Hearing From You&lt;/h2&gt;
&lt;p&gt;As always, if you have feedback regarding RDF.rb please contact us either &lt;a href="http://github.com/datagraph"&gt;privately&lt;/a&gt; or via the &lt;a href="http://lists.w3.org/Archives/Public/public-rdf-ruby/"&gt;public-rdf-ruby@w3.org&lt;/a&gt; mailing list. Plain and simple bug reports, however, should more preferably go directly to the &lt;a href="http://github.com/bendiken/rdf/issues"&gt;issue queue&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;p&gt;Be sure to follow &lt;a href="http://twitter.com/datagraph"&gt;@datagraph&lt;/a&gt;, &lt;a href="http://twitter.com/bendiken"&gt;@bendiken&lt;/a&gt;, &lt;a href="http://twitter.com/bhuga"&gt;@bhuga&lt;/a&gt;, and &lt;a href="http://twitter.com/gkellogg"&gt;@gkellogg&lt;/a&gt; on Twitter for the latest updates on RDF.rb as they happen.&lt;/p&gt;

    </description>
    <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-12-30T13:00:00Z</dc:date>
    <dc:creator>Arto Bendiken</dc:creator>
    <dc:subject>Ruby</dc:subject>
    <dc:subject>RDF</dc:subject>
    <dc:subject>Linked Data</dc:subject>
    <dc:subject>Semantic Web</dc:subject>
    <dc:subject>SPARQL</dc:subject>
    <dc:source rdf:resource="http://blog.datagraph.org/2010/12/rdf-for-ruby"/>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </item>
  <item rdf:about="http://blog.datagraph.org/2010/05/spira">
    <title>Spira: A Linked Data ORM for Ruby</title>
    <link>http://blog.datagraph.org/2010/05/spira</link>
    <description>&lt;p&gt;I've just released Spira, a first draft of an RDF ORM, where the 'R' can mean RDF
or Resource at your pleasure.  It's an easy way to create Ruby objects out of
RDF data.  The name is from Latin, for 'breath of life'--it's time to
give those resource URIs some character.  It looks like this (feel free to
copy-paste):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'spira'
require 'rdf/ntriples'

repo = "http://datagraph.org/jhacker/foaf.nt"
Spira.add_repository(:default, RDF::Repository.load(repo))

class Person
  include Spira::Resource

  property :name,  :predicate =&amp;gt; FOAF.name
  property :nick,  :predicate =&amp;gt; FOAF.nick
end

jhacker = RDF::URI("http://datagraph.org/jhacker/#self").as(Person)
jhacker.name #=&amp;gt; "J. Random Hacker"
jhacker.nick #=&amp;gt; "jhacker"
jhacker.name = "Some Other Hacker"
jhacker.save!
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="why_a_new_project"&gt;Why a new project?&lt;/h2&gt;
&lt;p&gt;I try not to start new projects lightly.  There's plenty of good stuff out
there.  But there wasn't quite what I wanted.&lt;/p&gt;
&lt;p&gt;First of all, I want to program in Ruby, so it needed to be Ruby.  Spira, while
different, has a lot of overlap with a traditional ORM, and I was on the fence
for a while about starting Spira or trying to implement things in DataMapper.
There's already an &lt;a href="http://rdf.rubyforge.org"&gt;RDF.rb&lt;/a&gt; backend for DataMapper, which is cool, but using it
really cuts you off from RDF as RDF.  It's more about making RDF work how
DataMapper likes it.  DataMapper's storage adapter interface is an implicit
data model, one that is not RDF's, and it is not quite what I wanted.&lt;/p&gt;
&lt;p&gt;On the RDF-specific front, there's ActiveRDF.  ActiveRDF is based on SPARQL
directly, and thus, while not hiding RDF from you, only gives you access via
Redland.  The Redland Ruby bindings have problems, and do not represent the
entire RDF ecosystem.  I wanted to start on something that completely
abstracted away the data model, so I could focus on the problem at hand, which
means RDF.rb.  The difference is in allowing me to focus on what I'm focusing
on: there exists a perfectly good, working SPARQL client storage adapter for
RDF.rb, but it's one of many pluggable backends instead of a requirement.&lt;/p&gt;
&lt;p&gt;Lastly, while both of those projects would represent a workable starting point,
this was something of a journey of exploration in terms of semantics.  Spira
was going to be &lt;strike&gt;'open world'&lt;/strike&gt; 'open model' from the start; I
specifically wanted something that could read foreign data.  By 'open model' I
mean that Spira does not expect that a class definition is the authoritative,
exclusive, or complete definition of a model class.  That turns out to make
Spira have some important semantic differences from ORMs oriented around object
or relational databases.  Stumbling on them was part of the fun, and even if I
could have twisted DataMapper around the problem, I'm not sure that starting
from there would have had me focusing on the core semantics.&lt;/p&gt;
&lt;p&gt;So I decided to start something new.  To be fair, Spira would suck a lot more
were it not for the projects that came before it.  In particular, it owes an
intellectual debt to DataMapper, which has a generally sane model, readable
code, and had to cover a lot of ground that any object-whatever-mapper would.
It takes some digging, but as an example, one can find &lt;a href="http://groups.google.com/group/datamapper/browse_thread/thread/570fee8fbcdf0c08"&gt;IRC logs&lt;/a&gt; where the
DataMapper team discusses the ups and downs of identity map implementations in
Ruby.  That stuff is amazing to have available without spending hundreds of
hours fighting it yourself, and again, it saves me a lot of trial and error on
ancilliary considerations.&lt;/p&gt;
&lt;h2 id="making_things_simple"&gt;Making things simple&lt;/h2&gt;
&lt;p&gt;Spira's core use case is allowing programmers to create Ruby objects
representing an aspect of an RDF resource.  I'm still working on which
terminology I like best, but I am leaning towards calling instances of Spira
classes 'a projection of a given RDF resource as a Spira resource.'  In the
simplest of terms, Spira tries to let you create classes that easily get and
set values for properties that correspond to RDF predicates.  The README will
explain it better than I want to in this post (now available in &lt;a href="http://github.com/datagraph/spira"&gt;Github&lt;/a&gt; and
&lt;a href="http://spira.rubyforge.org"&gt;Yardoc&lt;/a&gt; flavors).&lt;/p&gt;
&lt;p&gt;The hopeful end result is a way to access the RDF data model in a way that
agile web programmers have come to expect, without forcing them to get bogged
down into a world of ontologies, rule languages, inference levels, and lord
knows what-all else.  RDF has taken off in the enterprise because of power user
features, and we're approaching a critical mass of RDFa publishing, but it's
not yet on anyone's radar as a data model for their next weekend project.  I
think that's a shame--RDF's schema-free model should be the easiest thing in
the world to get started on.  So in addition to hopefully being an open-model
ORM, here's hoping Spira is a step in the adoption of RDF as a day-to-day data
model.&lt;/p&gt;
&lt;h2 id="so_whats_open_model_mean"&gt;So what's 'Open Model' mean?&lt;/h2&gt;
&lt;p&gt;Any useful abstraction layer is about applying constraints.  Normal ORMs hide
the power of relational databases to make them into proper object databases.
Spira constrains you to a particular aspect of a resource.  That means that in
the aspect of 'Person', a resource's name is a given predicate, and they only
have one.  A person might also have a label, multiple names, a comment,
function as a category or tag, have friends, have accounts, have tons of other
stuff, but if all you want is their age, you just want to say &lt;code&gt;person.name&lt;/code&gt; and
&lt;code&gt;person.age&lt;/code&gt;.  The goal here is to let you use data (or at least, to have
defined behavior for data) that you cannot say for sure meets any sort of
criteria you set in Spira.  Spira will have defined behavior for when data does
not match a model class, and will still let you use that data easily,
pretending it came from a closed system.  That's good enough surprisingly often.&lt;/p&gt;
&lt;p&gt;That open-model part is where tough semantics come in.  As an example, I had
intended to publish, with Spira, a reference implementation of SIOC.  The SIOC
core classes are in widespread use, so surely this would find some use, I
figured.  But it's not so simple to make a reference implementation unless you
limit your possibilities.  For example, a SIOC post can have topics (a sub-class of
dcterms:subject).  These topics are RDF resources which may be one (or, I
suppose, both, or neither) of two classes defined in the &lt;a href="http://rdfs.org/sioc/types"&gt;SIOC types ontology&lt;/a&gt;,
Category or Tag.  These two classes have completely different
semantics.  Now, a Spira class could be created to deal with either of them,
but to use that class usefully, you'd always be checking what it is, since the
semantics are different.  Spira will eventually have helpers to help you decide
what to do here, but the point is that in RDF, a 'reference implementation'
often doesn't make sense as a concept.  However, this is at least in principle
representable in Spira--I'm not sure it could be done in a traditional ORM, as
it doesn't really match the single-table inheritance model.&lt;/p&gt;
&lt;p&gt;Instead, I hope Spira classes are simple enough--throw away, even--that you
can define them when you need them.  Indeed, defining them programmatically
is obvious with the framework in place, I just haven't done it yet.&lt;/p&gt;
&lt;p&gt;Another example of differing semantics would be instance creation.  An RDF
resource does not 'exist or not'.  It's either the subject of triples or not.
So what would it mean to create an instance of a Spira resource and save it
when it had no fields?  Would one save a triple declaring the resource to be an
RDF resource?  How about saving the RDF type, should that happen if one has not
saved fields?  There are good arguments for several options.  It's just not the
same model as the 'find, create, find_or_create' trio of constructors that the
world has grown used to, since the identifiers are global and always exist.
Primary keys do not come into existence to allow reference to an object, the
key &lt;em&gt;is&lt;/em&gt; the object.  I dodged the question and now do construction based on
&lt;code&gt;RDF::URI&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;Instantiation looks either like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RDF::URI("http://example.org/bob").as(Person)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Person.for(RDF::URI("http://example.org/bob"))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There's no finding or creating.  Resources just are.  Creating a Spira object
is creating the projection of that resource as a class.  If you've told Spira
about a repository where some information about that resource may or may not
exist, great, but it's not required.&lt;/p&gt;
&lt;p&gt;As another example, I see a lot of need for validations on creating an
instance, not just saving one, as in traditional ORMs.  RDF is not like the
data fed to a traditional ORM, which is generally created by that ORM or by a
known list of applications, managed by a set of hard constraints and schema.
RDF data is often found, and used, in the wild.&lt;/p&gt;
&lt;p&gt;There's still a ton left to do, but lots of stuff already works.  The
&lt;a href="http://github.com/datagraph/spira"&gt;README&lt;/a&gt; has a good rundown of where things stand.  I'd enumerate the to-do
list, but I'd rather not feed that to Google, and it's long enough anyway that
if certain deficencies quickly become obvious, I'd attack them first.&lt;/p&gt;
&lt;p&gt;Anyways, hope someone has fun with it.  &lt;code&gt;gem install spira&lt;/code&gt; are the magic
words.  If you want to spoil the magic, the code is &lt;a href="http://github.com/datagraph/spira"&gt;on Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;small&gt;The original version of this post used the term 'Open World' instead of 'Open
Model' willy-nilly throughout, but I was corrected from using the term outside
its strict meaning in terms of inference.  See the comments.  If a term exists
for what I'm describing at this level of abstraction, I'm all ears.&lt;/small&gt;&lt;/em&gt;&lt;/p&gt;</description>
    <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-05-21T01:00:00Z</dc:date>
    <dc:creator>Ben Lavender</dc:creator>
    <dc:subject>Spira</dc:subject>
    <dc:subject>Ruby</dc:subject>
    <dc:subject>ORM</dc:subject>
    <dc:subject>RDF</dc:subject>
    <dc:subject>RDF.rb</dc:subject>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </item>
  <item rdf:about="http://blog.datagraph.org/2010/04/rdf-nosql-diff">
    <title>How RDF Databases Differ from Other NoSQL Solutions</title>
    <link>http://blog.datagraph.org/2010/04/rdf-nosql-diff</link>
    <description>&lt;p&gt;&lt;em&gt;This &lt;a href="http://www.semanticoverflow.com/questions/723/rdf-storages-vs-other-nosql-storages/755#755"&gt;started out&lt;/a&gt; as an answer at &lt;a href="http://www.semanticoverflow.com/"&gt;Semantic Overflow&lt;/a&gt; on how RDF database systems differ from other currently available NoSQL solutions. I've here expanded the answer somewhat and added some general-audience context.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.w3.org/RDF/"&gt;RDF&lt;/a&gt; database systems are the only standardized &lt;a href="http://en.wikipedia.org/wiki/NoSQL"&gt;NoSQL&lt;/a&gt; solutions available at the moment, being built on a &lt;a href="http://rdfabout.com/quickintro.xpd"&gt;simple, uniform data model&lt;/a&gt; and a &lt;a href="http://en.wikipedia.org/wiki/SPARQL"&gt;powerful, declarative query language&lt;/a&gt;. These systems offer data portability and toolchain interoperability among the dozens of competing implementations that are available at present, avoiding any need to bet the farm on a particular product or vendor.&lt;/p&gt;
&lt;p&gt;In case you're not familiar with the term, NoSQL ("Not only SQL") is a &lt;a href="http://nosql-database.org/"&gt;loosely-defined&lt;/a&gt; umbrella moniker for describing the new generation of non-relational database systems that have sprung up in the last several years. These systems tend to be inherently distributed, schema-less, and horizontally scalable. Present-day NoSQL solutions can be broadly categorized into four groups:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Key-value databases&lt;/strong&gt; are familiar to anyone who has worked with the likes of the venerable &lt;a href="http://en.wikipedia.org/wiki/Berkeley_DB"&gt;Berkeley DB&lt;/a&gt;. These systems are about as simple as databases get, being in essence variations on the theme of a persistent hash table. Current examples include &lt;a href="http://memcachedb.org/"&gt;MemcacheDB&lt;/a&gt;, &lt;a href="http://1978th.net/tokyocabinet/"&gt;Tokyo Cabinet&lt;/a&gt;, &lt;a href="http://code.google.com/p/redis/"&gt;Redis&lt;/a&gt; and &lt;a href="http://aws.amazon.com/simpledb/"&gt;SimpleDB&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Document databases&lt;/strong&gt; are key-value stores that treat stored values as &lt;a href="http://en.wikipedia.org/wiki/Semi-structured_data"&gt;semi-structured data&lt;/a&gt; instead of as opaque blobs. Prominent examples at the moment include &lt;a href="http://couchdb.apache.org/"&gt;CouchDB&lt;/a&gt;, &lt;a href="http://www.mongodb.org/"&gt;MongoDB&lt;/a&gt; and &lt;a href="http://www.slideshare.net/hemulen/introducing-riak"&gt;Riak&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wide-column databases&lt;/strong&gt; tend to draw inspiration from Google's &lt;a href="http://en.wikipedia.org/wiki/BigTable"&gt;BigTable&lt;/a&gt; model. Open-source examples include &lt;a href="http://cassandra.apache.org/"&gt;Cassandra&lt;/a&gt;, &lt;a href="http://hadoop.apache.org/hbase/"&gt;HBase&lt;/a&gt; and &lt;a href="http://hypertable.org/"&gt;Hypertable&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Graph databases&lt;/strong&gt; include generic solutions like &lt;a href="http://www.slideshare.net/emileifrem/neo4j-the-benefits-of-graph-databases-oscon-2009"&gt;Neo4j&lt;/a&gt;, &lt;a href="http://infogrid.org/"&gt;InfoGrid&lt;/a&gt; and &lt;a href="http://code.google.com/p/hypergraphdb/"&gt;HyperGraphDB&lt;/a&gt; as well as all the numerous RDF-centric solutions out there: &lt;a href="http://www.franz.com/agraph/allegrograph/"&gt;AllegroGraph&lt;/a&gt;, &lt;a href="http://4store.org/"&gt;4store&lt;/a&gt;, &lt;a href="http://virtuoso.openlinksw.com/dataspace/dav/wiki/Main/"&gt;Virtuoso&lt;/a&gt;, and &lt;a href="http://www.w3.org/2001/sw/wiki/Category:Triple_Store"&gt;many, many others&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;RDF database systems form the largest subset of this last NoSQL category. RDF data can be thought of in terms of a decentralized &lt;a href="http://en.wikipedia.org/wiki/Directed_graph"&gt;directed labeled graph&lt;/a&gt; wherein the arcs start with subject URIs, are labeled with predicate URIs, and end up pointing to object URIs or scalar values. Other equally valid ways to understand RDF data include the resource-centric approach (which maps well to object-oriented programming paradigms and to &lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"&gt;RESTful&lt;/a&gt; architectures) and the statement-centric view (the &lt;em&gt;object-attribute-value&lt;/em&gt; or &lt;a href="http://en.wikipedia.org/wiki/Entity-attribute-value_model"&gt;EAV&lt;/a&gt; model).&lt;/p&gt;
&lt;p&gt;Without just now extolling too much the virtues of RDF as a &lt;em&gt;particular&lt;/em&gt; data model, the key differentiator here is that RDF database systems embrace and build upon W3C's &lt;a href="http://linkeddata.org/"&gt;Linked Data&lt;/a&gt; technology stack and are the only &lt;em&gt;standardized&lt;/em&gt; NoSQL solutions available at the moment. This means that RDF-based solutions, when compared to run-of-the-mill NoSQL database systems, have benefits such as the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A simple and uniform standard data model.&lt;/strong&gt; NoSQL databases typically have one-off, ad-hoc data models and capabilities designed specifically for each implementation in question. As a rule, these data models are neither interoperable nor standardized. Take e.g. Cassandra, which has a somewhat baroque &lt;a href="http://wiki.apache.org/cassandra/DataModel"&gt;data model&lt;/a&gt; that "can most easily be thought of as a four or five dimensional hash" and the specifics of which are described in a wiki page, &lt;a href="http://arin.me/blog/wtf-is-a-supercolumn-cassandra-data-model"&gt;blog posts&lt;/a&gt; here and there, and ultimately only nailed down in version-specific API documentation and the code base itself. Compare to RDF database systems that all share the same &lt;a href="http://www.w3.org/RDF/"&gt;well-specified and W3C-standardized&lt;/a&gt; data model at their base.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;A powerful standard query language.&lt;/strong&gt; NoSQL databases typically &lt;a href="http://www.slideshare.net/harrikauhanen/nosql-3376398"&gt;do not provide&lt;/a&gt; any high-level &lt;a href="http://en.wikipedia.org/wiki/Declarative_programming"&gt;declarative&lt;/a&gt; query language equivalent of SQL. Querying these databases is a programmatic data-model-specific, language-specific and even application-specific affair. Where query languages do exist, they are entirely implementation-specific (think SimpleDB or GQL). &lt;a href="http://en.wikipedia.org/wiki/SPARQL"&gt;SPARQL&lt;/a&gt; is a very big win for RDF databases here, providing a standardized and interoperable query language that even non-programmers can make use of, and one which meets or exceeds SQL in its capabilities and power while retaining much of the familiar syntax.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Standardized data interchange formats.&lt;/strong&gt; RDBMSes have (somewhat implementation-specific) SQL dumps, and some NoSQL databases have import/export capability from/to implementation-specific structures expressed in an XML or JSON format. RDF databases, by contrast, all have import/export capability based on well-defined, standardized, entirely implementation-agnostic serialization formats such as &lt;a href="http://blog.datagraph.org/2010/03/grepping-ntriples"&gt;N-Triples&lt;/a&gt; and &lt;a href="http://sw.deri.org/2008/07/n-quads/"&gt;N-Quads&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From the preceding points it follows that RDF-based NoSQL solutions enjoy some very concrete advantages such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data portability.&lt;/strong&gt; Should you need to switch between competing database systems in-house, to make use of multiple different solutions concurrently, or to share data with external parties, your data travels with you without needing to write and utilize any custom glue code for converting some ad-hoc export format and data structure into some other incompatible ad-hoc import format and data structure.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Toolchain interoperability.&lt;/strong&gt; The RDBMS world has its various database abstraction layers, but the very concept is nonsensical for NoSQL solutions in general (see "ad-hoc data model"). RDF solutions, however, represent a special case: libraries and toolchains for RDF are typically only loosely coupled to any particular DBMS implementation. Learn to use and program with &lt;a href="http://jena.sourceforge.net/"&gt;Jena&lt;/a&gt; or &lt;a href="http://www.openrdf.org/"&gt;Sesame&lt;/a&gt; for Java and Scala, &lt;a href="http://www.rdflib.net/"&gt;RDFLib&lt;/a&gt; for Python, or &lt;a href="http://blog.datagraph.org/2010/03/rdf-for-ruby"&gt;RDF.rb&lt;/a&gt; for Ruby, and it generally doesn't matter which particular RDF-based system you are accessing. Just as with RDBMS-based database abstraction layers, your RDF-based code does not need to change merely because you wish to do the equivalent of switching from MySQL to PostgreSQL.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No vendor or product lock-in.&lt;/strong&gt; If the RDF database solution &lt;em&gt;A&lt;/em&gt; was easy to get going with but eventually for some reason hits a brick wall, just switch to RDF database solution &lt;em&gt;B&lt;/em&gt; or &lt;em&gt;C&lt;/em&gt; or any other of the many available interoperable solutions. Unlike switching between two non-RDF solutions, this does not have to be a big deal. Needless to say there are also ecosystem benefits with regards to the available talent pool and the commercial support options.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Future proof.&lt;/strong&gt; With RDF now &lt;a href="http://www.youtube.com/watch?v=3YcZ3Zqk0a8"&gt;emerging&lt;/a&gt; as the definitive standard for publishing &lt;a href="http://linkeddata.org/"&gt;Linked Data&lt;/a&gt; on the web, and being entirely built on top of indelibly-established lower-level standards like &lt;a href="http://en.wikipedia.org/wiki/Uniform_Resource_Identifier"&gt;URIs&lt;/a&gt;, it's not an unreasonable bet that your RDF data will still be usable as-is by, say, &lt;a href="http://en.wikipedia.org/wiki/Year_2038_problem"&gt;2038&lt;/a&gt;. It's not at all evident, however, that the same could be asserted for any of the other NoSQL solutions out there at the moment, many which will inevitably prove to be rather short-lived in the big picture.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;RDF-based systems also offer unique advantages such as support for globally-addressable row identifiers and property names, web-wide decentralized and dynamic schemas, data modeling standards and tooling for creating and publishing such schemas, metastandards for being able to declaratively specify that one piece of information entails another, and inference engines that implement such data transformation rules.&lt;/p&gt;
&lt;p&gt;All these features are mainly due to the characteristics and capabilities of RDF's data model, though, and have already been amply described elsewhere, so I won't go further into them just here and now. If you wish to learn more about RDF in general, a great place to start would be the excellent &lt;a href="http://rdfabout.com/intro/?section=contents"&gt;RDF in Depth&lt;/a&gt; tutorial by Joshua Tauberer.&lt;/p&gt;
&lt;p&gt;And should you be interested in the growing intersection between the NoSQL and Linked Data communities, you will be certain to enjoy the recording of Sandro Hawke's presentation &lt;a href="http://comlounge.tv/databases/cltv46"&gt;Toward Standards for NoSQL&lt;/a&gt; (&lt;a href="http://www.w3.org/2010/Talks/0311-nosql/talk.pdf"&gt;slides&lt;/a&gt;, &lt;a href="http://decentralyze.com/2010/03/09/rdf-meets-nosql/"&gt;blog post&lt;/a&gt;) at the &lt;a href="http://nosql.mypopescu.com/post/443539413/reports-from-nosql-live-in-boston"&gt;NoSQL Live in Boston&lt;/a&gt; conference in March 2010.&lt;/p&gt;</description>
    <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-04-22T20:00:00Z</dc:date>
    <dc:creator>Arto Bendiken</dc:creator>
    <dc:subject>RDF</dc:subject>
    <dc:subject>NoSQL</dc:subject>
    <dc:subject>comparison</dc:subject>
    <dc:subject>diff</dc:subject>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </item>
  <item rdf:about="http://blog.datagraph.org/2010/04/parsing-rdf-with-ruby">
    <title>Parsing and Serializing RDF Data with Ruby</title>
    <link>http://blog.datagraph.org/2010/04/parsing-rdf-with-ruby</link>
    <description>&lt;p&gt;In this tutorial we'll learn how to parse and serialize &lt;a href="http://www.w3.org/RDF/"&gt;RDF&lt;/a&gt; data using the &lt;a href="http://blog.datagraph.org/2010/03/rdf-for-ruby"&gt;RDF.rb&lt;/a&gt; library for &lt;a href="http://ruby-lang.org/"&gt;Ruby&lt;/a&gt;. There exist a number of &lt;a href="http://linkeddata.org/"&gt;Linked Data&lt;/a&gt; serialization formats based on RDF, and you can use most of them with RDF.rb.&lt;/p&gt;
&lt;p&gt;To follow along and try out the code examples in this tutorial, you need only a computer with Ruby and &lt;a href="http://rubygems.org/"&gt;RubyGems&lt;/a&gt; installed. Any recent Ruby 1.8.x or 1.9.x version will do fine, as will JRuby 1.4.0 or newer.&lt;/p&gt;
&lt;h2&gt;Supported RDF formats&lt;/h2&gt;
&lt;p&gt;These are the RDF serialization formats that you can parse and serialize with RDF.rb at present:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Format      | Implementation        | RubyGems gem
------------|-----------------------|-------------
N-Triples   | RDF::NTriples         | rdf
Turtle      | RDF::Raptor::Turtle   | rdf-raptor
RDF/XML     | RDF::Raptor::RDFXML   | rdf-raptor
RDFa        | RDF::Raptor::RDFa     | rdf-raptor
RDF/JSON    | RDF::JSON             | rdf-json
TriX        | RDF::TriX             | rdf-trix
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;RDF.rb in and of itself is a relatively lightweight gem that includes built-in support only for the &lt;a href="http://blog.datagraph.org/2010/03/grepping-ntriples"&gt;N-Triples&lt;/a&gt; format. Support for the other listed formats is available through add-on plugins such as &lt;a href="http://rdf.rubyforge.org/raptor/"&gt;RDF::Raptor&lt;/a&gt;, &lt;a href="http://rdf.rubyforge.org/json/"&gt;RDF::JSON&lt;/a&gt; and &lt;a href="http://rdf.rubyforge.org/trix/"&gt;RDF::TriX&lt;/a&gt;, each one packaged as a separate gem. This approach keeps the core library fleet on its metaphorical feet and avoids introducing any XML or JSON parser dependencies for RDF.rb itself.&lt;/p&gt;
&lt;p&gt;Installing support for all these formats in one go is easy enough:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo gem install rdf rdf-raptor rdf-json rdf-trix
Successfully installed rdf-0.1.9
Successfully installed rdf-raptor-0.2.1
Successfully installed rdf-json-0.1.0
Successfully installed rdf-trix-0.0.3
4 gems installed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the RDF::Raptor gem requires that the &lt;a href="http://librdf.org/raptor/"&gt;Raptor RDF Parser&lt;/a&gt; library and command-line tools be available on the system where it is used. Here follow quick and easy Raptor installation instructions for the Mac and the most common Linux and BSD distributions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo port install raptor             # Mac OS X with MacPorts
$ sudo fink install raptor-bin         # Mac OS X with Fink
$ sudo aptitude install raptor-utils   # Ubuntu / Debian
$ sudo yum install raptor              # Fedora / CentOS / RHEL
$ sudo zypper install raptor           # openSUSE
$ sudo emerge raptor                   # Gentoo Linux
$ sudo pkg_add -r raptor               # FreeBSD
$ sudo pkg_add raptor                  # OpenBSD / NetBSD
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;For more information on installing and using Raptor, see our previous tutorial &lt;a href="http://blog.datagraph.org/2010/04/transmuting-ntriples"&gt;RDF for Intrepid Unix Hackers: Transmuting N-Triples&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Consuming RDF data&lt;/h2&gt;
&lt;p&gt;If you're in a hurry and just want to get to consuming RDF data right away, the following is really the only thing you need to know:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'rdf'
require 'rdf/ntriples'

graph = RDF::Graph.load("http://datagraph.org/jhacker/foaf.nt")
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, we first load up RDF.rb as well as support for the N-Triples format. After that, we use a convenience method on the &lt;a href="http://rdf.rubyforge.org/RDF/Graph.html"&gt;&lt;code&gt;RDF::Graph&lt;/code&gt;&lt;/a&gt; class to fetch and parse RDF data directly from a web URL in one go. (The &lt;code&gt;load&lt;/code&gt; method can take either a file name or a URL.)&lt;/p&gt;
&lt;p&gt;All RDF.rb parser plugins declare which MIME content types and file extensions they are capable of handling, which is why in the above example RDF.rb knows how to instantiate an N-Triples parser to read the &lt;code&gt;foaf.nt&lt;/code&gt; file at the given URL.&lt;/p&gt;
&lt;p&gt;In the same way, RDF.rb will auto-detect any other RDF file formats as long as you've loaded up support for them using one or more of the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'rdf/ntriples' # Support for N-Triples (.nt)
require 'rdf/raptor'   # Support for RDF/XML (.rdf) and Turtle (.ttl)
require 'rdf/json'     # Support for RDF/JSON (.json)
require 'rdf/trix'     # Support for TriX (.xml)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that if you need to read RDF files containing multiple named graphs (in a serialization format that supports named graphs, such as TriX), you probably want to be using &lt;a href="http://rdf.rubyforge.org/RDF/Repository.html"&gt;&lt;code&gt;RDF::Repository&lt;/code&gt;&lt;/a&gt; instead of &lt;code&gt;RDF::Graph&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;repository = RDF::Repository.load("http://datagraph.org/jhacker/foaf.nt")
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The difference between the two is that RDF statements in &lt;code&gt;RDF::Repository&lt;/code&gt; instances can contain an optional context (i.e. they can be &lt;em&gt;quads&lt;/em&gt;), whereas statements in an &lt;code&gt;RDF::Graph&lt;/code&gt; instance always have the same context (i.e. they are &lt;em&gt;triples&lt;/em&gt;). In other words, repositories contain one or more graphs, which you can access as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;repository.each_graph do |graph|
  puts graph.inspect
end
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Introspecting RDF formats&lt;/h2&gt;
&lt;p&gt;RDF.rb's parsing and serialization APIs are based on the following three base classes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://rdf.rubyforge.org/RDF/Format.html"&gt;&lt;code&gt;RDF::Format&lt;/code&gt;&lt;/a&gt; is used to describe particular RDF serialization formats.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rdf.rubyforge.org/RDF/Reader.html"&gt;&lt;code&gt;RDF::Reader&lt;/code&gt;&lt;/a&gt; is the base class for RDF parser implementations.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rdf.rubyforge.org/RDF/Writer.html"&gt;&lt;code&gt;RDF::Writer&lt;/code&gt;&lt;/a&gt; is the base class for RDF serializer implementations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you know something about the file format you want to parse or serialize, you can obtain a format specifier class for it in any of the following ways:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'rdf/raptor'

RDF::Format.for(:rdfxml)       #=&amp;gt; RDF::Raptor::RDFXML::Format
RDF::Format.for("input.rdf")
RDF::Format.for(:file_name      =&amp;gt; "input.rdf")
RDF::Format.for(:file_extension =&amp;gt; "rdf")
RDF::Format.for(:content_type   =&amp;gt; "application/rdf+xml")
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once you have such a format specifier class, you can then obtain the parser/serializer implementations for it as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;format = RDF::Format.for("input.nt")   #=&amp;gt; RDF::NTriples::Format
reader = format.reader                 #=&amp;gt; RDF::NTriples::Reader
writer = format.writer                 #=&amp;gt; RDF::NTriples::Writer
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There also exist corresponding factory methods on &lt;code&gt;RDF::Reader&lt;/code&gt; and &lt;code&gt;RDF::Writer&lt;/code&gt; directly:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;reader = RDF::Reader.for("input.nt")   #=&amp;gt; RDF::NTriples::Reader
writer = RDF::Writer.for("output.nt")  #=&amp;gt; RDF::NTriples::Writer
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above is what RDF.rb relies on internally to obtain the correct parser implementation when you pass in a URL or file name to &lt;code&gt;RDF::Graph.load&lt;/code&gt; -- or indeed to any other method that needs to auto-detect a serialization format and to delegate responsibility for parsing/serialization to the appropriate implementation class.&lt;/p&gt;
&lt;h2&gt;Parsing RDF data&lt;/h2&gt;
&lt;p&gt;If you need to be more explicit about parsing RDF data, for instance because the dataset won't fit into memory and you wish to process it statement by statement, you'll need to use &lt;a href="http://rdf.rubyforge.org/RDF/Reader.html"&gt;&lt;code&gt;RDF::Reader&lt;/code&gt;&lt;/a&gt; directly.&lt;/p&gt;
&lt;h3 id="parsing_rdf_statements_from_a_file"&gt;Parsing RDF statements from a file&lt;/h3&gt;
&lt;p&gt;RDF parser implementations generally support a streaming-compatible subset of the &lt;a href="http://rdf.rubyforge.org/RDF/Enumerable.html"&gt;&lt;code&gt;RDF::Enumerable&lt;/code&gt;&lt;/a&gt; interface, all of which is based on the &lt;code&gt;#each_statement&lt;/code&gt; method. Here's how to read in an RDF file enumerated statement by statement:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'rdf/raptor'

RDF::Reader.open("foaf.rdf") do |reader|
  reader.each_statement do |statement|
    puts statement.inspect
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using &lt;code&gt;RDF::Reader.open&lt;/code&gt; with a Ruby block ensures that the input file is automatically closed after you're done with it.&lt;/p&gt;
&lt;h3 id="parsing_rdf_statements_from_a_url"&gt;Parsing RDF statements from a URL&lt;/h3&gt;
&lt;p&gt;As before, you can generally use an &lt;code&gt;http://&lt;/code&gt; or &lt;code&gt;https://&lt;/code&gt; URL anywhere that you could use a file name:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'rdf/json'

RDF::Reader.open("http://datagraph.org/jhacker/foaf.json") do |reader|
  reader.each_statement do |statement|
    puts statement.inspect
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="parsing_rdf_statements_from_a_string"&gt;Parsing RDF statements from a string&lt;/h3&gt;
&lt;p&gt;Sometimes you already have the serialized RDF contents in a memory buffer somewhere, for example as retrieved from a database. In such a case, you'll want to obtain the parser implementation class as shown before, and then use &lt;code&gt;RDF::Reader.new&lt;/code&gt; directly:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'rdf/ntriples'

input = open('http://datagraph.org/jhacker/foaf.nt').read

RDF::Reader.for(:ntriples).new(input) do |reader|
  reader.each_statement do |statement|
    puts statement.inspect
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;RDF::Reader&lt;/code&gt; constructor uses duck typing and accepts any input (for example, &lt;code&gt;IO&lt;/code&gt; or &lt;code&gt;StringIO&lt;/code&gt; objects) that responds to the &lt;code&gt;#readline&lt;/code&gt; method. If no input argument is given, input data will by default be read from the standard input.&lt;/p&gt;
&lt;h2&gt;Serializing RDF data&lt;/h2&gt;
&lt;p&gt;Serializing RDF data works much the same way as parsing: when serializing to a named output file, the correct serializer implementation is auto-detected based on the given file extension.&lt;/p&gt;
&lt;h3 id="serializing_rdf_statements_into_an_output_file"&gt;Serializing RDF statements into an output file&lt;/h3&gt;
&lt;p&gt;RDF serializer implementations generally support an append-only subset of the &lt;a href="http://rdf.rubyforge.org/RDF/Mutable.html"&gt;&lt;code&gt;RDF::Mutable&lt;/code&gt;&lt;/a&gt; interface, primarily the &lt;code&gt;#insert&lt;/code&gt; method and its alias &lt;code&gt;#&amp;lt;&amp;lt;&lt;/code&gt;. Here's how to write out an RDF file statement by statement:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'rdf/ntriples'
require 'rdf/raptor'

data = RDF::Graph.load("http://datagraph.org/jhacker/foaf.nt")

RDF::Writer.open("output.rdf") do |writer|
  data.each_statement do |statement|
    writer &amp;lt;&amp;lt; statement
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once again, using &lt;code&gt;RDF::Writer.open&lt;/code&gt; with a Ruby block ensures that the output file is automatically flushed and closed after you're done writing to it.&lt;/p&gt;
&lt;h3 id="serializing_rdf_statements_into_a_string_result"&gt;Serializing RDF statements into a string result&lt;/h3&gt;
&lt;p&gt;A common use case is serializing an RDF graph into a string buffer, for example when serving RDF data from a &lt;a href="http://www.rubyonrails.org/"&gt;Rails&lt;/a&gt; application. &lt;code&gt;RDF::Writer&lt;/code&gt; has a convenience &lt;code&gt;buffer&lt;/code&gt; class method that builds up output in a &lt;code&gt;StringIO&lt;/code&gt; under the covers and then returns a string when all is said and done:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'rdf/ntriples'

output = RDF::Writer.for(:ntriples).buffer do |writer|
  subject = RDF::Node.new
  writer &amp;lt;&amp;lt; [subject, RDF.type, RDF::FOAF.Person]
  writer &amp;lt;&amp;lt; [subject, RDF::FOAF.name, "J. Random Hacker"]
  writer &amp;lt;&amp;lt; [subject, RDF::FOAF.mbox, RDF::URI("mailto:jhacker@example.org")]
  writer &amp;lt;&amp;lt; [subject, RDF::FOAF.nick, "jhacker"]
end
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="customizing_the_serializer_output"&gt;Customizing the serializer output&lt;/h3&gt;
&lt;p&gt;If a particular serializer implementation supports options such as namespace prefix declarations or a base URI, you can pass in those options to &lt;code&gt;RDF::Writer.open&lt;/code&gt; or &lt;code&gt;RDF::Writer.new&lt;/code&gt; as keyword arguments:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RDF::Writer.open("output.ttl", :base_uri =&amp;gt; "http://rdf.rubyforge.org/")
RDF::Writer.for(:rdfxml).new($stdout, :base_uri =&amp;gt; "http://rdf.rubyforge.org/")
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="support_channels"&gt;Support channels&lt;/h2&gt;
&lt;p&gt;That's all for now, folks. For more information on the APIs touched upon in this tutorial, please refer to the RDF.rb &lt;a href="http://rdf.rubyforge.org/"&gt;API documention&lt;/a&gt;. If you have any questions, don't hesitate to ask for help on &lt;a href="http://swig.xmlhack.com/"&gt;#swig&lt;/a&gt; or the &lt;a href="http://lists.w3.org/Archives/Public/public-rdf-ruby/"&gt;public-rdf-ruby@w3.org&lt;/a&gt; mailing list.&lt;/p&gt;</description>
    <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-04-21T16:00:00Z</dc:date>
    <dc:creator>Arto Bendiken</dc:creator>
    <dc:subject>RDF</dc:subject>
    <dc:subject>Ruby</dc:subject>
    <dc:subject>parsing</dc:subject>
    <dc:subject>serializing</dc:subject>
    <dc:subject>RDF.rb</dc:subject>
    <dc:subject>RDF::Format</dc:subject>
    <dc:subject>RDF::Reader</dc:subject>
    <dc:subject>RDF::Writer</dc:subject>
    <dc:subject>how-to</dc:subject>
    <dc:subject>tutorial</dc:subject>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </item>
  <item rdf:about="http://blog.datagraph.org/2010/04/rdf-repository-howto">
    <title>How to Build an SQL Storage Adapter for RDF Data with Ruby</title>
    <link>http://blog.datagraph.org/2010/04/rdf-repository-howto</link>
    <description>&lt;p&gt;&lt;a href="http://blog.datagraph.org/2010/03/rdf-for-ruby"&gt;RDF.rb&lt;/a&gt; is approaching two thousand downloads &lt;a href="http://rubygems.org/gems/rdf"&gt;on RubyGems&lt;/a&gt;,
and while it has &lt;a href="http://rdf.rubyforge.org/"&gt;good documentation&lt;/a&gt; it could still use
some more tutorials.  I recently needed to get RDF.rb working with a
PostgreSQL storage backend in order to work with RDF data in a &lt;a href="http://guides.rails.info/3_0_release_notes.html"&gt;Rails 3.0&lt;/a&gt;
application hosted on &lt;a href="http://heroku.com/"&gt;Heroku&lt;/a&gt;.  I thought I'd keep track of what I did so
that I could discuss the notable parts.&lt;/p&gt;
&lt;p&gt;In this tutorial we'll be implementing an RDF.rb storage adapter called
&lt;code&gt;RDF::DataObjects::Repository&lt;/code&gt;, which is a simplified version of what I
eventually ended up with.  If you want the real thing, check it out on
&lt;a href="http://github.com/bhuga/rdf-do"&gt;GitHub&lt;/a&gt; and read &lt;a href="http://rdf.rubyforge.org/do/"&gt;the docs&lt;/a&gt;.  This
tutorial will only cover the SQLite backend and won't concern itself with
database indexes, performance tweaks, or any other distractions from the
essential RDF.rb interfaces we'll focus on.  There's a copy of the
simplified code used in the tutorial at &lt;a href="http://github.com/bhuga/rdf-repository-howto"&gt;the tutorial's project page&lt;/a&gt;. 
And should you be inspired to build something similar of your own, I have
set up an RDF.rb &lt;a href="http://github.com/bhuga/rdf-repository-skeleton"&gt;storage adapter skeleton&lt;/a&gt; at GitHub.  Click &lt;em&gt;fork&lt;/em&gt;, grep
for lines containing a &lt;code&gt;TODO&lt;/code&gt; comment, and dive right in.&lt;/p&gt;
&lt;p&gt;I'll mention, briefly, that I chose &lt;a href="http://github.com/datamapper/do"&gt;DataObjects&lt;/a&gt; as the database
abstraction layer, but I don't want to dwell on that -- this post is about
RDF.  DataObjects is just a way to use common methods to talk to different
databases at the SQL level.  It's a leaky abstraction, because we'll want to
be using some SQL constraints to enforce statement uniqueness but those
constraints need to be done differently for different databases.  That means
we still have to get down to the level of database-specific SQL, distasteful
as that may be in this day and age.  However, given that I wanted to be able
to target PostgreSQL and SQLite both, DataObjects is still helpful.&lt;/p&gt;
&lt;h4&gt;Requirements&lt;/h4&gt;
&lt;p&gt;You just need a few gems for the example repository.  This ought to get you
going.  Even if you have these, make sure you have the latest; RDF.rb gets
updated frequently.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo gem install rdf rdf-spec rspec do_sqlite3
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Testing First&lt;/h2&gt;
&lt;p&gt;So where do we start?  Tests, of course.  RDF.rb has factored out its mixin
specs to the &lt;a href="http://rdf.rubyforge.org/spec/"&gt;RDF::Spec&lt;/a&gt; gem, which provides the &lt;a href="http://rspec.info/documentation/"&gt;RSpec shared example groups&lt;/a&gt;
that are also used by RDF.rb for its own tests.  Thus, here is the
complete spec file for the in-memory reference implementation of
&lt;code&gt;RDF::Repository&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require File.join(File.dirname(__FILE__), 'spec_helper')
require 'rdf/spec/repository'

describe RDF::Repository do
  before :each do
    @repository = RDF::Repository.new
  end

  # @see lib/rdf/spec/repository.rb
  it_should_behave_like RDF_Repository
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you haven't seen something like this before, that's an RSpec shared
example group, and it's awesome.  Anything can use the same specs as RDF.rb
itself to verify that it conforms to the interfaces defined by RDF.rb, and
that's exactly what we'll be doing in this tutorial.  Let's implement that
for our repository:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# spec/sqlite3.spec
$:.unshift File.dirname(__FILE__) + "/../lib/"

require 'rdf'
require 'rdf/do'
require 'rdf/spec/repository'
require 'do_sqlite3'

describe RDF::DataObjects::Repository do
  context "The SQLite adapter" do
    before :each do
      @repository = RDF::DataObjects::Repository.new "sqlite3::memory:"
    end

    after :each do
      # DataObjects pools connections, and only allows 8 at once.  We have
      # more than 60 tests.
      DataObjects::Sqlite3::Connection.__pools.clear
    end

    it_should_behave_like RDF_Repository
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you're new to RSpec, run the tests with the &lt;code&gt;spec&lt;/code&gt; command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ spec -cfn spec/sqlite3.spec
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These fail miserably right now, of course, since we don't have an implementation.
So let's make one.&lt;/p&gt;
&lt;h2&gt;Initial implementation&lt;/h2&gt;
&lt;p&gt;RDF.rb's interface for an RDF store is &lt;a href="http://rdf.rubyforge.org/RDF/Repository.html"&gt;&lt;code&gt;RDF::Repository&lt;/code&gt;&lt;/a&gt;.  That interface
is itself composed of a number of mixins: &lt;code&gt;RDF::Enumerable&lt;/code&gt;, &lt;code&gt;RDF::Queryable&lt;/code&gt;,
&lt;code&gt;RDF::Mutable&lt;/code&gt;, and &lt;code&gt;RDF::Durable&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RDF::Queryable&lt;/code&gt; has a base implementation that works on anything which
implements &lt;code&gt;RDF::Enumerable&lt;/code&gt;.  And &lt;code&gt;RDF::Durable&lt;/code&gt; only provides boolean
methods for clients to ask if it is &lt;code&gt;durable?&lt;/code&gt; or not; the default is that a
repository reports that it is indeed durable, so we don't need to do anything
there.&lt;/p&gt;
&lt;p&gt;The takeaway is that to create an RDF.rb storage adapter, we need to implement
&lt;code&gt;RDF::Enumerable&lt;/code&gt; and &lt;code&gt;RDF::Mutable&lt;/code&gt;, and the rest will fall into place.
Indeed, the reference implementation is little more than an array which
implements these interfaces.&lt;/p&gt;
&lt;p&gt;It turns out we can get away with just three methods to implement those two
interfaces:  &lt;code&gt;RDF::Enumerable#each&lt;/code&gt;, &lt;code&gt;RDF::Mutable#insert_statement&lt;/code&gt;, and
&lt;code&gt;RDF::Mutable#delete_statement&lt;/code&gt;.  The default implementations will use these to
build up any missing methods.  That means we need to implement those first, so
that we have a base to pass our tests.  Then we can iterate further, replacing
methods which iterate over every statement with methods more appropriate for
our backend.&lt;/p&gt;
&lt;p&gt;Here's a repository which doesn't implement much more than those three methods.
We'll use it as a starting point.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# lib/rdf/do.rb

require 'rdf'
require 'rdf/ntriples'
require 'data_objects'
require 'do_sqlite3'
require 'enumerator'

module RDF
  module DataObjects
    class Repository &amp;lt; ::RDF::Repository

      def initialize(options)
        @db = ::DataObjects::Connection.new(options)
        exec('CREATE TABLE IF NOT EXISTS quads (
              `subject` varchar(255), 
              `predicate` varchar(255),
              `object` varchar(255), 
              `context` varchar(255), 
              UNIQUE (`subject`, `predicate`, `object`, `context`))')
      end

      # @see RDF::Enumerable#each.
      def each(&amp;amp;block)
        if block_given?
          reader = result('SELECT * FROM quads')
          while reader.next!
            block.call(RDF::Statement.new(
                  :subject   =&amp;gt; unserialize(reader.values[0]),
                  :predicate =&amp;gt; unserialize(reader.values[1]),
                  :object    =&amp;gt; unserialize(reader.values[2]),
                  :context   =&amp;gt; unserialize(reader.values[3])))

          end
        else
          ::Enumerable::Enumerator.new(self,:each)
        end
      end

      # @see RDF::Mutable#insert_statement
      def insert_statement(statement)
        sql = 'REPLACE INTO `quads` (subject, predicate, object, context) VALUES (?, ?, ?, ?)'
        exec(sql,serialize(statement.subject),serialize(statement.predicate), 
                 serialize(statement.object), serialize(statement.context)) 
      end

      # @see RDF::Mutable#delete_statement
      def delete_statement(statement)
        sql = 'DELETE FROM `quads` where (subject = ? AND predicate = ? AND object = ? AND context = ?)'
        exec(sql,serialize(statement.subject),serialize(statement.predicate), 
                 serialize(statement.object), serialize(statement.context)) 
      end

      ## These are simple helpers to serialize and unserialize component
      # fields.  We use an explicit empty string for null values for clarity in
      # this example; we cannot use NULL, as SQLite considers NULLs as
      # distinct from each other when using the uniqueness constraint we
      # added when we created the table.  It would let us insert duplicate
      # with a NULL context.
      def serialize(value)
        RDF::NTriples::Writer.serialize(value) || ''
      end
      def unserialize(value)
        value == '' ? nil : RDF::NTriples::Reader.unserialize(value)
      end

      ## These are simple helpers for DataObjects
      def exec(sql, *args)
        @db.create_command(sql).execute_non_query(*args)
      end
      def result(sql, *args)
        @db.create_command(sql).execute_reader(*args)
      end

    end
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we have a repository.  Poof, done, that's it.  You can get a copy of this
intermediate repository at &lt;a href="http://github.com/bhuga/rdf-repository-howto"&gt;the tutorial page&lt;/a&gt; and run the specs for yourself.  It's not
very efficient for SQL yet, but this is all it takes, strictly speaking.&lt;/p&gt;
&lt;p&gt;Since they are so important, the three main methods deserve a little more attention:&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;each&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Each is the only thing we have to implement to get information out after we've
put it in.  &lt;code&gt;RDF::Enumerable&lt;/code&gt; will provide us tons of things like
&lt;code&gt;each_subject&lt;/code&gt;, &lt;code&gt;has_subject?&lt;/code&gt;, &lt;code&gt;each_predicate&lt;/code&gt;, &lt;code&gt;has_predicate?&lt;/code&gt;, etc.  If
you were watching the spec output, you'll notice we ran tests for
&lt;code&gt;RDF::Queryable&lt;/code&gt;.  The default implementation will use &lt;code&gt;RDF::Enumerable&lt;/code&gt;'s
methods to implement basic querying.  This means we can already do things like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Note that #load actually comes from insert_statement, see below
repo.load('http://datagraph.org/jhacker/foaf.nt')
repo.query(:subject =&amp;gt; RDF::URI.new('http://datagraph.org/jhacker/foaf'))
#=&amp;gt; RDF::Enumerable of statements with given URI as subject
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that if a block is not sent, it's defined to return an
&lt;code&gt;Enumerable::Enumerator&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;RDF::Queryable&lt;/code&gt;, which defines &lt;code&gt;#query&lt;/code&gt;, is probably the thing we can improve
the most on with SQL as opposed to the reference implementation.  We'll revisit
it below.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;insert_statement&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;insert_statement&lt;/code&gt; inserts an &lt;code&gt;RDF::Statement&lt;/code&gt; into the repository.  It's
pretty straightforward.  It gives us access to default implementations of
things like &lt;code&gt;RDF::Mutable#load&lt;/code&gt;, which will load a file by name or import a
remote resource:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;repo.load('http://datagraph.org/jhacker/foaf.nt')
repo.count
#=&amp;gt; 10
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;delete_statement&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;delete_statement&lt;/code&gt; deletes an &lt;code&gt;RDF::Statement&lt;/code&gt;. Again, it's straightforward, and it's
used to implement things like &lt;code&gt;RDF::Mutable#clear&lt;/code&gt;, which empties the
repository:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;repo.load('http://datagraph.org/jhacker/foaf.nt')
repo.clear
repo.count
#=&amp;gt; 0
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Iterate and Improve&lt;/h2&gt;
&lt;p&gt;Since we already have a nice test suite that we can pass, we can add
functionality incrementally.  For example, let's implement
&lt;code&gt;RDF::Enumerable#count&lt;/code&gt; in a fashion that does not require us to enumerate each
statement, which is clearly not ideal for a SQL-based system:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# lib/rdf/do.rb

def count
  result = result('SELECT COUNT(*) FROM quads')
  result.next!
  result.values.first
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The tests still pass, we can move on.  Wash, rinse, repeat; probably every method
in &lt;code&gt;RDF::Enumerable&lt;/code&gt; and &lt;code&gt;RDF::Mutable&lt;/code&gt; can be done more efficiently with SQL.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;RDF::Queryable&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;RDF::Queryable&lt;/code&gt; is worth mentioning on its own, because the interface takes a
lot of options.  Specifically, it can take a Hash, a smashed Array, an
RDF::Statement, or a Query object.  Fortunately, we can call &lt;code&gt;super&lt;/code&gt; to defer
to the reference implementation if we get arguments we don't understand, so we
can again be iterative here.&lt;/p&gt;
&lt;p&gt;We can start by implementing the hash version, which is the most convienent for
doing the actual SQL query later.  The hash version takes a hash which may have
keys for &lt;code&gt;:subject&lt;/code&gt;, &lt;code&gt;:predicate&lt;/code&gt;, &lt;code&gt;:object&lt;/code&gt;, and &lt;code&gt;:context&lt;/code&gt;, and returns an
&lt;code&gt;RDF::Enumerable&lt;/code&gt; which contains all statements matching those parameters&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# lib/rdf/do.rb

      def query(pattern, &amp;amp;block)
        case pattern
          when Hash
            statements = []
            reader = query_hash(pattern)
            while reader.next!
              statements &amp;lt;&amp;lt; RDF::Statement.new(
                      :subject   =&amp;gt; unserialize(reader.values[0]),
                      :predicate =&amp;gt; unserialize(reader.values[1]),
                      :object    =&amp;gt; unserialize(reader.values[2]),
                      :context   =&amp;gt; unserialize(reader.values[3]))
            end
            case block_given?
              when true
                statements.each(&amp;amp;block)
              else
                statements.extend(RDF::Enumerable, RDF::Queryable)
            end
          else
            super(pattern) 
        end
      end

      def query_hash(hash)
        conditions = []
        params = []
        [:subject, :predicate, :object, :context].each do |resource|
          unless hash[resource].nil?
            conditions &amp;lt;&amp;lt; "#{resource.to_s} = ?"
            params     &amp;lt;&amp;lt; serialize(hash[resource])
          end
        end
        where = conditions.empty? ? "" : "WHERE "
        where &amp;lt;&amp;lt; conditions.join(' AND ')
        result('SELECT * FROM quads ' + where, *params)
      end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our specs still pass.  Note this trick:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;statements.extend(RDF::Enumerable, RDF::Queryable)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;RDF::Queryable&lt;/code&gt; is defined to return something which implements &lt;code&gt;RDF::Enumerable&lt;/code&gt;
and &lt;code&gt;RDF::Queryable&lt;/code&gt;.  Since the only thing we need to implement &lt;code&gt;RDF::Enumerable&lt;/code&gt;
is &lt;code&gt;#each&lt;/code&gt;, and &lt;code&gt;Array&lt;/code&gt; already implements that, we can simply extend this &lt;code&gt;Array&lt;/code&gt;
instance with the mixins and return it.&lt;/p&gt;
&lt;p&gt;Note also that while we have taken care of the hard part, we're still calling the
reference implementation if we don't know how to handle our arguments.  Now we
can start adding those other query arguments:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# lib/rdf/do.rb

      def query(pattern, &amp;amp;block)
        case pattern
          when RDF::Statement
            query(pattern.to_hash)
          when Array
            query(RDF::Statement.new(*pattern))
          when Hash
      .
      .
      .
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our specs still pass!  Moving on, there's a lot more we can implement.  And
once we have implemented it in a straightforward way, we can still implement
things like multiple inserts, paging, and more, all transparant to the user.
You can see the full list of methods to implement in the docs, but don't be
afraid to dive into the code.&lt;/p&gt;
&lt;p&gt;If you do, don't forget that RDF.rb is completely &lt;a href="http://unlicense.org/"&gt;public domain&lt;/a&gt;, so if you want to
copy-paste to bootstrap your implementation, feel free.&lt;/p&gt;
&lt;h4&gt;Any questions?&lt;/h4&gt;
&lt;p&gt;Hopefully this is enough to get you started.  Remember, the code is at
&lt;a href="http://github.com/bhuga/rdf-repository-howto"&gt;the tutorial page&lt;/a&gt;, and don't forget to check out the &lt;a href="http://github.com/bhuga/rdf-repository-skeleton"&gt;storage adapter skeleton&lt;/a&gt;.
The &lt;a href="http://rdf.rubyforge.org/"&gt;RDF.rb documentation&lt;/a&gt; have a lot of information on the
APIs you'll be using.&lt;/p&gt;
&lt;p&gt;And last but not least, a good place to ask questions or leave a comment is on
the &lt;a href="http://lists.w3.org/Archives/Public/public-rdf-ruby/"&gt;W3C RDF-Ruby mailing list&lt;/a&gt;.&lt;/p&gt;</description>
    <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-04-06T09:00:00Z</dc:date>
    <dc:creator>Ben Lavender</dc:creator>
    <dc:subject>RDF</dc:subject>
    <dc:subject>Ruby</dc:subject>
    <dc:subject>RDF.rb</dc:subject>
    <dc:subject>RDF::Repository</dc:subject>
    <dc:subject>DataObjects</dc:subject>
    <dc:subject>SQL</dc:subject>
    <dc:subject>PostgreSQL</dc:subject>
    <dc:subject>SQLite</dc:subject>
    <dc:subject>how-to</dc:subject>
    <dc:subject>tutorial</dc:subject>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </item>
  <item rdf:about="http://blog.datagraph.org/2010/04/transmuting-ntriples">
    <title>RDF for Intrepid Unix Hackers: Transmuting N-Triples</title>
    <link>http://blog.datagraph.org/2010/04/transmuting-ntriples</link>
    <description>&lt;p&gt;This is the second part in an ongoing &lt;em&gt;RDF for Intrepid Unix Hackers&lt;/em&gt; article series. In the &lt;a href="http://blog.datagraph.org/2010/03/grepping-ntriples"&gt;previous part&lt;/a&gt;, we learned how to process &lt;a href="http://www.w3.org/RDF/"&gt;RDF&lt;/a&gt; data in the line-oriented, whitespace-separated &lt;a href="http://en.wikipedia.org/wiki/N-Triples"&gt;N-Triples&lt;/a&gt; serialization format by pipelining standard Unix tools such as &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;awk&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That was all well and good, but what to do if your RDF data isn't already in &lt;a href="http://en.wikipedia.org/wiki/N-Triples"&gt;N-Triples&lt;/a&gt; format?
Today we'll see how to install and use the excellent &lt;a href="http://librdf.org/raptor/"&gt;Raptor RDF Parser Library&lt;/a&gt; to convert RDF from one serialization format to another.&lt;/p&gt;
&lt;h3&gt;Installing the Raptor RDF Parser tools&lt;/h3&gt;
&lt;p&gt;The &lt;a href="http://librdf.org/raptor/"&gt;Raptor&lt;/a&gt; toolkit includes a handy command-line utility called &lt;a href="http://librdf.org/raptor/rapper.html"&gt;&lt;code&gt;rapper&lt;/code&gt;&lt;/a&gt;, which can be used to convert RDF data between most of the various popular RDF serialization formats.&lt;/p&gt;
&lt;p&gt;Installing Raptor is straightforward on most development and deployment platforms; here's how to install Raptor on Mac OS X with &lt;a href="http://www.macports.org/"&gt;MacPorts&lt;/a&gt; and on any of the most common Linux and BSD distributions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ [sudo] port install raptor             # Mac OS X with MacPorts
$ [sudo] fink install raptor-bin         # Mac OS X with Fink
$ [sudo] aptitude install raptor-utils   # Ubuntu / Debian
$ [sudo] yum install raptor              # Fedora / CentOS / RHEL
$ [sudo] zypper install raptor           # openSUSE
$ [sudo] emerge raptor                   # Gentoo Linux
$ [sudo] pacman -S raptor                # Arch Linux
$ [sudo] pkg_add -r raptor               # FreeBSD
$ [sudo] pkg_add raptor                  # OpenBSD / NetBSD
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The subsequent examples all assume that you have successfully installed Raptor and thus have the &lt;code&gt;rapper&lt;/code&gt; utility available in your &lt;code&gt;$PATH&lt;/code&gt;. To make sure that &lt;code&gt;rapper&lt;/code&gt; is indeed available, just ask it to output its version number as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ rapper --version
1.4.21
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We'll be using version 1.4.21 for this tutorial, but any 1.4.x release from 1.4.5 onwards should do fine for present purposes -- so don't worry if your distribution provides a slightly older version.&lt;/p&gt;
&lt;p&gt;Should you have any trouble getting &lt;code&gt;rapper&lt;/code&gt; set up, you can ask for help on the &lt;a href="http://swig.xmlhack.com/"&gt;#swig&lt;/a&gt; channel on &lt;a href="http://freenode.net/"&gt;IRC&lt;/a&gt; or on the Raptor &lt;a href="http://librdf.org/lists/"&gt;mailing list&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Transmuting RDF/XML into N-Triples&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://www.w3.org/TR/REC-rdf-syntax/"&gt;RDF/XML&lt;/a&gt; is the standard RDF serialization specified by W3C back before the dot-com bust. Despite some newer, more human-friendly formats, a great deal of the RDF data out there in the wild is still made available in this format.&lt;/p&gt;
&lt;p&gt;For example, every valid &lt;a href="http://web.resource.org/rss/1.0/"&gt;RSS 1.0&lt;/a&gt;-compatible feed is, in principle, also a valid RDF/XML document (but note that the same is &lt;em&gt;not&lt;/em&gt; true for non-RDF formats like RSS 2.0 or Atom). So, let's grab the RSS feed for this blog and define a Bash shell alias for converting RDF/XML into N-Triples using &lt;code&gt;rapper&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias rdf2nt="rapper -i rdfxml -o ntriples"

$ curl http://blog.datagraph.org/index.rss &amp;gt; index.rdf

$ rdf2nt index.rdf &amp;gt; index.nt
rapper: Parsing URI file://index.rdf with parser rdfxml
rapper: Serializing with serializer ntriples
rapper: Parsing returned 106 triples
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty easy, huh? It gets even easier, because &lt;code&gt;rapper&lt;/code&gt; actually supports fetching URLs directly. Typically Raptor is built with &lt;code&gt;libcurl&lt;/code&gt; support, so it supports the same set of URL schemes as does the &lt;code&gt;curl&lt;/code&gt; command itself. This means that e.g. any &lt;code&gt;http://&lt;/code&gt;, &lt;code&gt;https://&lt;/code&gt; and &lt;code&gt;ftp://&lt;/code&gt; input arguments will work right out of the box, so that we can combine our previous last two commands as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ rdf2nt http://blog.datagraph.org/index.rss &amp;gt; index.nt
rapper: Parsing URI http://blog.datagraph.org/index.rss with parser rdfxml
rapper: Serializing with serializer ntriples
rapper: Parsing returned 106 triples
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Transmuting Turtle into N-Triples&lt;/h3&gt;
&lt;p&gt;After RDF/XML, &lt;a href="http://en.wikipedia.org/wiki/Turtle_(syntax)"&gt;Turtle&lt;/a&gt; is probably the most widespread RDF format out there. It is a subset of &lt;a href="http://en.wikipedia.org/wiki/Notation3"&gt;Notation3&lt;/a&gt; and a superset of N-Triples, hitting a sweet spot for both expressiveness and conciseness. It is also much more pleasant to write by hand than XML, so personal &lt;a href="http://en.wikipedia.org/wiki/FOAF_(software)"&gt;FOAF&lt;/a&gt; files in particular tend to be authored in Turtle and then converted, e.g. using &lt;code&gt;rapper&lt;/code&gt;, into a variety of formats when published on the &lt;a href="http://linkeddata.org/"&gt;Linked Data&lt;/a&gt; web.&lt;/p&gt;
&lt;p&gt;For this next example, let's grab &lt;a href="http://datagraph.org/bendiken/foaf"&gt;my FOAF file&lt;/a&gt; in Turtle format and convert it into N-Triples:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias ttl2nt="rapper -i turtle -o ntriples"

$ ttl2nt http://datagraph.org/bendiken/foaf.ttl &amp;gt; foaf.nt
rapper: Parsing URI http://datagraph.org/bendiken/foaf.ttl with parser turtle
rapper: Serializing with serializer ntriples
rapper: Parsing returned 16 triples
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just as easy as with RDF/XML. And you'll notice that this time around we did the downloading and the conversion in a single step by letting &lt;code&gt;rapper&lt;/code&gt; worry about fetching the data directly from the URL in question.&lt;/p&gt;
&lt;h3&gt;Transmuting N-Triples into other formats&lt;/h3&gt;
&lt;p&gt;Conversely, you can of course also use &lt;code&gt;rapper&lt;/code&gt; to convert any N-Triples input data into other RDF serialization formats such as Turtle, RDF/XML and &lt;a href="http://n2.talis.com/wiki/RDF_JSON_Specification"&gt;RDF/JSON&lt;/a&gt;. You need only swap the arguments to the &lt;code&gt;-i&lt;/code&gt; and &lt;code&gt;-o&lt;/code&gt; options and you're good to go.&lt;/p&gt;
&lt;p&gt;So, let's define a couple more handy aliases:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias nt2ttl="rapper -i ntriples -o turtle"
$ alias nt2rdf="rapper -i ntriples -o rdfxml-abbrev"
$ alias nt2json="rapper -i ntriples -o json"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can quickly and easily convert any N-Triples data into other RDF formats:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ nt2ttl  index.nt &amp;gt; index.ttl
$ nt2rdf  index.nt &amp;gt; index.rdf
$ nt2json index.nt &amp;gt; index.json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can define similar aliases for any input/output permutation provided by &lt;code&gt;rapper&lt;/code&gt;. To find out the full list of input and output RDF serialization formats supported by your version of the program, run &lt;code&gt;rapper --help&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ rapper --help
...
Main options:
  -i FORMAT, --input FORMAT   Set the input format/parser to one of:
    rdfxml          RDF/XML (default)
    ntriples        N-Triples
    turtle          Turtle Terse RDF Triple Language
    trig            TriG - Turtle with Named Graphs
    rss-tag-soup    RSS Tag Soup
    grddl           Gleaning Resource Descriptions from Dialects of Languages
    guess           Pick the parser to use using content type and URI
    rdfa            RDF/A via librdfa
...
  -o FORMAT, --output FORMAT  Set the output format/serializer to one of:
    ntriples        N-Triples (default)
    turtle          Turtle
    rdfxml-xmp      RDF/XML (XMP Profile)
    rdfxml-abbrev   RDF/XML (Abbreviated)
    rdfxml          RDF/XML
    rss-1.0         RSS 1.0
    atom            Atom 1.0
    dot             GraphViz DOT format
    json-triples    RDF/JSON Triples
    json            RDF/JSON Resource-Centric
...
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Defining more &lt;code&gt;rapper&lt;/code&gt; aliases&lt;/h3&gt;
&lt;p&gt;Copy and paste the following code snippet into your &lt;code&gt;~/.bash_aliases&lt;/code&gt; or &lt;code&gt;~/.bash_profile&lt;/code&gt; file, and you will always have these aliases available when working with RDF data on the command line:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# rapper aliases from http://blog.datagraph.org/2010/04/transmuting-ntriples
alias any2nt="rapper -i guess -o ntriples"         # Anything to N-Triples
alias any2ttl="rapper -i guess -o turtle"          # Anything to Turtle
alias any2rdf="rapper -i guess -o rdfxml-abbrev"   # Anything to RDF/XML
alias any2json="rapper -i guess -o json"           # Anything to RDF/JSON
alias nt2ttl="rapper -i ntriples -o turtle"        # N-Triples to Turtle
alias nt2rdf="rapper -i ntriples -o rdfxml-abbrev" # N-Triples to RDF/XML
alias nt2json="rapper -i ntriples -o json"         # N-Triples to RDF/JSON
alias ttl2nt="rapper -i turtle -o ntriples"        # Turtle to N-Triples
alias ttl2rdf="rapper -i turtle -o rdfxml-abbrev"  # Turtle to RDF/XML
alias ttl2json="rapper -i turtle -o json"          # Turtle to RDF/JSON
alias rdf2nt="rapper -i rdfxml -o ntriples"        # RDF/XML to N-Triples
alias rdf2ttl="rapper -i rdfxml -o turtle"         # RDF/XML to Turtle
alias rdf2json="rapper -i rdfxml -o json"          # RDF/XML to RDF/JSON
alias json2nt="rapper -i json -o ntriples"         # RDF/JSON to N-Triples
alias json2ttl="rapper -i json -o ntriples"        # RDF/JSON to N-Triples
alias json2rdf="rapper -i json -o ntriples"        # RDF/JSON to N-Triples
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since each of these aliases is a mnemonic patterned after the file extensions for the input and output formats involved, remembering these is easy as pie. Note also that I've included four &lt;code&gt;any2*&lt;/code&gt; aliases that specify &lt;code&gt;guess&lt;/code&gt; as the input format to let &lt;code&gt;rapper&lt;/code&gt; try and automatically detect the serialization format for the input stream.&lt;/p&gt;
&lt;p&gt;A big thanks goes out to &lt;a href="http://www.dajobe.org/"&gt;Dave Beckett&lt;/a&gt; for having developed Raptor and for giving us the superbly useful N-Triples and Turtle serialization formats. I personally use &lt;code&gt;rapper&lt;/code&gt; and these aliases just about every single day, and I hope you find them as useful as I have.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://feeds.feedburner.com/datagraph"&gt;Stay tuned&lt;/a&gt; for more upcoming installments of &lt;em&gt;RDF for Intrepid Unix Hackers&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;small&gt;&lt;em&gt;Lest there be any doubt, all the code in this tutorial is hereby
released into the public domain using the &lt;a href="http://unlicense.org/"&gt;Unlicense&lt;/a&gt;. You are free to
copy, modify, publish, use, sell and distribute it in any way you please,
with or without attribution.&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;</description>
    <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-04-05T09:00:00Z</dc:date>
    <dc:creator>Arto Bendiken</dc:creator>
    <dc:subject>RDF</dc:subject>
    <dc:subject>Unix</dc:subject>
    <dc:subject>Raptor</dc:subject>
    <dc:subject>rapper</dc:subject>
    <dc:subject>N-Triples</dc:subject>
    <dc:subject>Turtle</dc:subject>
    <dc:subject>RDF/XML</dc:subject>
    <dc:subject>RDF/JSON</dc:subject>
    <dc:subject>how-to</dc:subject>
    <dc:subject>tutorial</dc:subject>
    <dc:subject>serialization</dc:subject>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </item>
  <item rdf:about="http://blog.datagraph.org/2010/03/rdf-isomorphism">
    <title>The Curious Case of RDF Graph Isomorphism</title>
    <link>http://blog.datagraph.org/2010/03/rdf-isomorphism</link>
    <description>&lt;p&gt;The first time I ever sat down to write some real RDF code, I started, as one always should, with some tests.  Most of them went fine, but then I had to write a test that compared the equality of two graphs; I think this was for a parser in Scala, sometime last year, but I've lost track of what exactly I was looking at.  In any case, what a can of worms I opened.&lt;/p&gt;
&lt;p&gt;It turns out that graph equality in RDF is hard.  The combination of blank and non-blank nodes makes it a &lt;a href="http://en.wikipedia.org/wiki/Graph_isomorphism_problem"&gt;graph isomorphism problem&lt;/a&gt; that I have not found an exact equivalence for in straight-up graph theory.  Graphs with named vertices and edges have easy solutions, graphs with unnamed vertices and edges have other, difficult solutions.  The difference, depending on the type of graph, can be between &lt;em&gt;O(n)&lt;/em&gt; and &lt;em&gt;O(n!)&lt;/em&gt; on the number of nodes, so when selecting a possible solution, we'd like to avoid solutions that don't take naming into account.&lt;/p&gt;
&lt;p&gt;The isomorphism problem is hard enough that many popular RDF implementations don't even include a solution for it.  &lt;a href="http://www.rdflib.net/"&gt;RDFLib&lt;/a&gt; for Python has an &lt;a href="http://code.google.com/p/rdflib/source/browse/trunk/rdflib/graph.py#780"&gt;approximation with a to-do note&lt;/a&gt;, I don't see an appropriate function in &lt;a href="http://librdf.org/docs/api/redland-model.html"&gt;Redland's model API&lt;/a&gt;, and &lt;a href="http://www.openrdf.org/"&gt;Sesame&lt;/a&gt; has &lt;a href="http://repo.aduna-software.org/websvn/filedetails.php?repname=aduna&amp;amp;path=%2Forg.openrdf%2Fsesame%2Ftrunk%2Fcore%2Fmodel%2Fsrc%2Fmain%2Fjava%2Forg%2Fopenrdf%2Fmodel%2Futil%2FModelUtil.java"&gt;an implementation&lt;/a&gt; with the following comment:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// FIXME: this recursive implementation has a high risk of
// triggering a stack overflow
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;My Java is rusty and I have no intention of polishing it up for this blog post, but I believe Sesame's implementation has factorial complexity.&lt;/p&gt;
&lt;p&gt;Now, don't get me wrong.  Those are all free projects, and it's a tough problem to do right.  We over at &lt;a href="http://blog.datagraph.org/"&gt;Datagraph&lt;/a&gt; just made do without an isomorphism function in either Scala or Ruby for several months rather than solve it.  So this is not intended to be a cheap shot at those projects -- in fact, we use both Redland and Sesame, and quite happily.  And if I'm wrong on the sparse nature of this landscape, someone please correct me.&lt;/p&gt;
&lt;p&gt;However, we're developing a new &lt;a href="http://rdf.rubyforge.org/"&gt;RDF library for Ruby&lt;/a&gt;, so when it came time to really solve the problem, we wanted to solve it right.  Like most problems in computer science, it's actually old news.  &lt;a href="http://semanticweb.org/wiki/Jeremy_J._Carroll"&gt;Jeremy Carroll&lt;/a&gt; solved it and &lt;a href="http://jena.cvs.sourceforge.net/viewvc/jena/jena/src/com/hp/hpl/mesa/rdf/jena/common/ModelMatcher.java?view=markup"&gt;implemented it&lt;/a&gt; for &lt;a href="http://jena.sourceforge.net/"&gt;Jena&lt;/a&gt; either before or after writing a &lt;a href="http://www.hpl.hp.com/techreports/2001/HPL-2001-293.pdf"&gt;great paper on the topic&lt;/a&gt;.  What I'm about to describe is more or less his algorithm, and while I slightly adjusted the following to my style, I'm not about to say much that his paper doesn't.  So just go read the paper if that's your preference.&lt;/p&gt;
&lt;p&gt;The algorithm can be described as a refinement of a naive &lt;em&gt;O(n!)&lt;/em&gt; graph isomorphism algorithm, in which each blank node is mapped onto each other blank node, followed by a consistency check.  The magic stems from RDF having these nifty &lt;a href="http://en.wikipedia.org/wiki/Uniform_Resource_Identifier"&gt;global identifiers&lt;/a&gt; for most vertices and all edges.  If we're smart about it, we can eliminate substantially all of the possible mappings before we try even our first speculative mapping.&lt;/p&gt;
&lt;p&gt;I haven't done the math, but it would seem that one could generate a pathological case graph which would be &lt;em&gt;O(n!)&lt;/em&gt;.  On the other hand, since RDF does not allow blank node predicates, and because the algorithm terminates on the first match, I haven't yet figured out how to create such a pathological graph for this algorithm.  Graphs tend to be either open enough to have a large number of solutions, one of which will be found quickly, or tight enough to have only one.&lt;/p&gt;
&lt;p&gt;The algorithm works as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Compare graph sizes and all statements without blank nodes.  If they do not match, fail.&lt;/li&gt;
&lt;li&gt;Repeat, for each graph:&lt;ol&gt;
&lt;li&gt;Repeat, for each blank node:&lt;ol&gt;
&lt;li&gt;Mark the node as grounded or not.  A grounded node has only non-blank nodes or grounded nodes in statements in which it appears.&lt;/li&gt;
&lt;li&gt;Create a signature for the node.  A signature consists of a canonical representation of all of the statements a node appears in.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Terminate unless we marked a node as grounded on this run.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Map grounded blank nodes to the other graph's grounded blank nodes where signatures match.&lt;/li&gt;
&lt;li&gt;If all nodes are mapped, we have a bijection, which we can return.&lt;/li&gt;
&lt;li&gt;Select ungrounded nodes from each graph with identical signatures.  Mark them as grounded, then recurse to step 2.&lt;/li&gt;
&lt;li&gt;If no ungrounded nodes have the same signature, or we have tried all matching pairs, a bijection does not exist.  Fail.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In something approaching day-to-day English, what's happening here is that after eliminating the simple possibilities, we're generating a hash of all of the elements that appear with a given node in a graph.  We then create a node-to-hash mapping.  As the hashes will be the same for blank nodes on both input graphs, we use that hash to eliminate possible matchings before we try them.  Instead of trying every mapping, we try mappings only on nodes with the same signature.  The end result is an algorithm that requires a fairly pathological case to recurse &lt;em&gt;at all&lt;/em&gt;, let alone to recurse deeply.  Nice.&lt;/p&gt;
&lt;p&gt;At any rate, you can see the details, along with some test cases to play with, in &lt;a href="http://rubygems.org/gems/rdf-isomorphic"&gt;&lt;code&gt;RDF::Isomorphic&lt;/code&gt;&lt;/a&gt; for RDF.rb.  This blog post coincides with release 0.1.0, which features a slightly improved signature algorithm, reducing the number of rounds required in some cases.  The &lt;a href="http://rdf.rubyforge.org/isomorphic/"&gt;documentation&lt;/a&gt; is also greatly improved -- I spent more time on this problem than I ever intended to, so I hope this can be a readable summary of the algorithm for anyone coming across this in the future.  Of course, RDF.rb's structure means almost anything using RDF.rb &lt;a href="http://blog.datagraph.org/2010/02/hacking-rdf-in-ruby"&gt;can be tested for isomorphism&lt;/a&gt; now, so hopefully it won't ever occur to you to read the code.&lt;/p&gt;
&lt;p&gt;Of course, &lt;code&gt;RDF::Isomorphic&lt;/code&gt; is in the &lt;a href="http://unlicense.org/"&gt;public domain&lt;/a&gt;, so should you find my implementation worthy, feel free to copy the code as directly as your framework or programming language allows.  And please feel free to do that without any obligation to provide attribution or any such silliness.&lt;/p&gt;</description>
    <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-03-12T20:00:00Z</dc:date>
    <dc:creator>Ben Lavender</dc:creator>
    <dc:subject>RDF</dc:subject>
    <dc:subject>Ruby</dc:subject>
    <dc:subject>RDF.rb</dc:subject>
    <dc:subject>RDF::Isomorphic</dc:subject>
    <dc:subject>isomorphism</dc:subject>
    <dc:subject>graph theory</dc:subject>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </item>
  <item rdf:about="http://blog.datagraph.org/2010/03/rdf-for-ruby">
    <title>RDF.rb: A Public-Domain RDF Library for Ruby</title>
    <link>http://blog.datagraph.org/2010/03/rdf-for-ruby</link>
    <description>&lt;p&gt;We have just released version 0.1.0 of &lt;a href="http://rubygems.org/gems/rdf"&gt;RDF.rb&lt;/a&gt;, our &lt;a href="http://www.w3.org/RDF/"&gt;RDF&lt;/a&gt; library for
&lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt;. This is the first generally useful release of the library, so I
will here introduce the design philosophy and object model of the library as
well as provide a tutorial to using its core classes.&lt;/p&gt;
&lt;p&gt;RDF.rb has &lt;a href="https://www.ohloh.net/p/rdf/factoids/2739953"&gt;extensive&lt;/a&gt; &lt;a href="http://rdf.rubyforge.org/"&gt;API documentation&lt;/a&gt; with
many inline code examples, enjoys comprehensive &lt;a href="http://rspec.info/"&gt;RSpec&lt;/a&gt; coverage, and is
immediately available via &lt;a href="http://rubygems.org/"&gt;RubyGems&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ [sudo] gem install rdf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once installed, to load up the library in your own Ruby projects you need
only do:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'rdf'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The RDF.rb &lt;a href="http://github.com/bendiken/rdf"&gt;source code repository&lt;/a&gt; is hosted on GitHub. You can
obtain a local working copy of the source code as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ git clone git://github.com/bendiken/rdf.git
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The Design Philosophy&lt;/h2&gt;
&lt;p&gt;The design philosophy for RDF.rb differs somewhat from previous efforts at
RDF libraries for Ruby. Instead of a feature-packed RDF library that
attempts to include everything but the kitchen sink, we have rather aimed
for something like a lowest common denominator with well-defined, finite
requirements.&lt;/p&gt;
&lt;p&gt;Thus, RDF.rb is perhaps quickest described in terms of what it &lt;em&gt;isn't&lt;/em&gt; and
what it &lt;em&gt;hasn't&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;RDF.rb does not have any dependencies other than the &lt;a href="http://rubygems.org/gems/addressable"&gt;Addressable&lt;/a&gt; gem
  which provides improved URI handling over Ruby's standard library. We
  also guarantee that RDF.rb will never add any hard dependencies that would
  compromise its use on popular alternative Ruby implementations such as
  &lt;a href="http://jruby.org/"&gt;JRuby&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RDF.rb does not provide any resource-centric, &lt;a href="http://en.wikipedia.org/wiki/Object-relational_mapping" title="object-relational mapper"&gt;ORM&lt;/a&gt;-like abstractions to
  hide the essential statement-oriented nature of the API. Such
  abstractions may be useful, but they are beyond the scope of RDF.rb
  itself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RDF.rb does not, and will not, include built-in support for any RDF
  serialization formats other than &lt;a href="http://en.wikipedia.org/wiki/N-Triples"&gt;N-Triples&lt;/a&gt; and &lt;a href="http://sw.deri.org/2008/07/n-quads/"&gt;N-Quads&lt;/a&gt;.
  However, it does define a &lt;a href="http://en.wikipedia.org/wiki/Domain-specific_language" title="domain-specific language"&gt;DSL&lt;/a&gt; and &lt;a href="http://rdf.rubyforge.org/RDF/Format.html"&gt;common API&lt;/a&gt; for adding
  support for other formats via third-party plugin gems. There presently
  exist RDF.rb-compatible &lt;a href="http://rubygems.org/gems/rdf-json"&gt;RDF::JSON&lt;/a&gt; and &lt;a href="http://rubygems.org/gems/rdf-trix"&gt;RDF::TriX&lt;/a&gt; gems that add
  initial &lt;a href="http://n2.talis.com/wiki/RDF_JSON_Specification"&gt;RDF/JSON&lt;/a&gt; and &lt;a href="http://www.w3.org/2004/03/trix/"&gt;TriX&lt;/a&gt; support, respectively.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RDF.rb does not, and will not, include built-in support for any particular
  persistent RDF storage systems. However, it does define the interfaces
  that such storage adapters could be written to. Again, add-on gems are
  the way to go, and there already exists an in-the-works RDF.rb-compatible
  &lt;a href="http://rubygems.org/gems/rdf-sesame"&gt;RDF::Sesame&lt;/a&gt; gem that enables using &lt;a href="http://www.openrdf.org/"&gt;Sesame 2.0&lt;/a&gt; HTTP endpoints
  with the &lt;a href="http://rdf.rubyforge.org/RDF/Repository.html"&gt;repository interface&lt;/a&gt; defined by RDF.rb.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RDF.rb does not, and will not, include any built-in &lt;a href="http://en.wikipedia.org/wiki/RDF_Schema"&gt;RDF Schema&lt;/a&gt; or
  &lt;a href="http://en.wikipedia.org/wiki/Web_Ontology_Language"&gt;OWL&lt;/a&gt; inference capabilities. There exists an in-the-works
  RDF.rb-compatible &lt;a href="http://rubygems.org/gems/rdfs"&gt;RDFS&lt;/a&gt; gem that is intended to provide a naive
  proof-of-concept implementation of a &lt;a href="http://en.wikipedia.org/wiki/Forward_chaining"&gt;forward-chaining&lt;/a&gt; inference
  engine for the RDF Schema entailment rules.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RDF.rb does not include any built-in &lt;a href="http://en.wikipedia.org/wiki/SPARQL"&gt;SPARQL&lt;/a&gt; functionality per se,
  though it will soon &lt;a href="http://rdf.rubyforge.org/RDF/Query.html"&gt;provide support&lt;/a&gt; for basic graph pattern
  (BGP) matching and could thus conceivably be used as the basis for a
  SPARQL engine written in Ruby.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RDF.rb does not come with a license statement, but rather with the
  stringent hope that you have a nice day. RDF.rb is 100% &lt;a href="http://unlicense.org/"&gt;free and
  unencumbered public domain software&lt;/a&gt;. You can copy, modify,
  use, and hack on it without any restrictions whatsoever.
  This means that authors of other RDF libraries for Ruby are perfectly
  welcome to steal any of our code, with or without attribution. So, if
  some code snippet or file may be of use to you, feel free to copy it and
  relicense it under whatever license you have released your own library
  with -- no need to include any copyright notices from us (since there are
  none), or even to mention us in the credits (we won't mind).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So that's what RDF.rb is not, but perhaps more important is what we want it
to be. There's no reason for simple RDF-based solutions to require enormous
complex libraries, storage engines, significant IDE configuration or XML
pushups. We're hoping to bring RDF to a world of agile programmers and
startups, and to bring existing &lt;a href="http://linkeddata.org/"&gt;Linked Data&lt;/a&gt; enthusiasts to a platform
that encourages rapid innovation and programmer happiness. And maybe
everyone can have some fun along the way!&lt;/p&gt;
&lt;p&gt;It is also our hope that the aforementioned minimalistic design approach and
extremely liberal licensing can help lead to the emergence of a
semi-standard Ruby object model for RDF, that is, a common core class
hierarchy and API that could be largely interoperable between a number of
RDF libraries for Ruby.&lt;/p&gt;
&lt;p&gt;With that in mind, let's proceed to have a look at RDF.rb's core object
model.&lt;/p&gt;
&lt;h2&gt;The Object Model&lt;/h2&gt;
&lt;p&gt;While RDF.rb is built to take full advantage of Ruby's &lt;a href="http://en.wikipedia.org/wiki/Duck_typing"&gt;duck typing&lt;/a&gt; and
&lt;a href="http://en.wikipedia.org/wiki/Mixin"&gt;mixins&lt;/a&gt;, it does also define a class hierarchy of RDF objects. If
nothing else, this inheritance tree is useful for &lt;code&gt;case/when&lt;/code&gt; matching and
also adheres to the &lt;a href="http://en.wikipedia.org/wiki/Principle_of_least_astonishment"&gt;principle of least surprise&lt;/a&gt; for developers
hailing from less dynamic programming languages.&lt;/p&gt;
&lt;p&gt;The RDF.rb core class hierarchy looks like the following, and will seem
instantly familiar to anyone acquainted with &lt;a href="http://www.openrdf.org/doc/sesame2/2.3.1/apidocs/org/openrdf/model/package-summary.html"&gt;Sesame's object model&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="RDF.rb class hierarchy" src="http://blog.datagraph.org/2010/03/rdf-for-ruby/classes.png"/&gt;&lt;/p&gt;

&lt;p&gt;The five core RDF.rb classes, all of them ultimately inheriting from
&lt;code&gt;RDF::Value&lt;/code&gt;, are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;RDF::Literal&lt;/code&gt; represents plain, language-tagged or datatyped literals.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RDF::URI&lt;/code&gt; represents URI references (URLs and URNs).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RDF::Node&lt;/code&gt; represents anonymous nodes (also known as blank nodes).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RDF::Statement&lt;/code&gt; represents RDF statements (also known as triples).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RDF::Graph&lt;/code&gt; represents anonymous or named graphs containing zero or
  more statements.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition, the two core RDF.rb interfaces (known as &lt;em&gt;mixins&lt;/em&gt; in Ruby
parlance) are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;RDF::Enumerable&lt;/code&gt; provides RDF-specific iteration methods for any
  collection of RDF statements.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RDF::Queryable&lt;/code&gt; provides RDF-specific query methods for any collection of
  RDF statements.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let's take a quick tour of each of these aforementioned core classes and
mixins.&lt;/p&gt;
&lt;h2&gt;Working with &lt;a href="http://rdf.rubyforge.org/RDF/URI.html"&gt;RDF::URI&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;URI references (URLs and URNs) are represented in RDF.rb as instances of the
&lt;code&gt;RDF::URI&lt;/code&gt; class, which is based on the excellent
&lt;a href="http://rubygems.org/gems/addressable"&gt;Addressable::URI&lt;/a&gt; library.&lt;/p&gt;
&lt;h3&gt;Creating a URI reference&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;RDF::URI&lt;/code&gt; constructor is overloaded to take either a URI string
(anything that responds to &lt;code&gt;#to_s&lt;/code&gt;, actually) or an options hash of URI
components. This means that the following are two equivalent ways of
constructing the same URI reference:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uri = RDF::URI.new("http://rdf.rubyforge.org/")

uri = RDF::URI.new({
  :scheme =&amp;gt; 'http',
  :host   =&amp;gt; 'rdf.rubyforge.org',
  :path   =&amp;gt; '/',
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The supported URI components are explained in the API documentation for
&lt;a href="http://addressable.rubyforge.org/api/classes/Addressable/URI.html#M000013"&gt;&lt;code&gt;Addressable::URI.new&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Getting the string representation of a URI&lt;/h3&gt;
&lt;p&gt;Turning a URI reference back into a string works as usual in Ruby:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uri.to_s        #=&amp;gt; "http://rdf.rubyforge.org/"
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Navigating URI hierarchies&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;RDF::URI&lt;/code&gt; supports the same set of instance methods as does
&lt;code&gt;Addressable::URI&lt;/code&gt;. This means that the following methods, and many more,
are available:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uri = RDF::URI.new("http://rubygems.org/gems/rdf")

uri.absolute?   #=&amp;gt; true
uri.relative?   #=&amp;gt; false
uri.scheme      #=&amp;gt; "http"
uri.authority   #=&amp;gt; "rubygems.org"
uri.host        #=&amp;gt; "rubygems.org"
uri.port        #=&amp;gt; nil
uri.path        #=&amp;gt; "/gems/rdf"
uri.basename    #=&amp;gt; "rdf"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In addition, &lt;code&gt;RDF::URI&lt;/code&gt; supports several convenience methods that can help
you navigate URI hierarchies without breaking a sweat:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uri = RDF::URI.new("http://rubygems.org/")
uri = uri.join("gems", "rdf")

uri.to_s        #=&amp;gt; "http://rubygems.org/gems/rdf"

uri.parent      #=&amp;gt; RDF::URI.new("http://rubygems.org/gems/")
uri.root        #=&amp;gt; RDF::URI.new("http://rubygems.org/")
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Working with &lt;a href="http://rdf.rubyforge.org/RDF/Node.html"&gt;RDF::Node&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Blank nodes are represented in RDF.rb as instances of the &lt;code&gt;RDF::Node&lt;/code&gt; class.&lt;/p&gt;
&lt;h3&gt;Creating a blank node with an implicit identifier&lt;/h3&gt;
&lt;p&gt;The simplest way to create a new blank node is as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bnode = RDF::Node.new
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will create a blank node with an identifier based on the internal Ruby
object ID of the &lt;code&gt;RDF::Node&lt;/code&gt; instance. This nicely serves us as a unique
identifier for the duration of the Ruby process:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bnode.id   #=&amp;gt; "2158816220"
bnode.to_s #=&amp;gt; "_:2158816220"
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Creating a blank node with a UUID identifier&lt;/h3&gt;
&lt;p&gt;You can also provide an explicit blank node identifier to the &lt;code&gt;RDF::Node&lt;/code&gt;
constructor. This is particularly useful when serializing or parsing RDF
data, where you generally need to maintain a mapping of blank node
identifiers to blank node instances.&lt;/p&gt;
&lt;p&gt;The constructor argument can be any string or any object that responds to
&lt;code&gt;#to_s&lt;/code&gt;. For example, say that you wanted to create a blank node instance
having a globally-unique &lt;a href="http://en.wikipedia.org/wiki/Universally_Unique_Identifier" title="universally unique identifier"&gt;UUID&lt;/a&gt; as its identifier. Here's how you would do
this with the help of the &lt;a href="http://rubygems.org/gems/uuid"&gt;UUID gem&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'uuid'

bnode = RDF::Node.new(UUID.generate)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above is a fairly common use case, so RDF.rb actually provides a
convenience class method for creating UUID-based blank nodes. The following
will use either the UUID or the &lt;a href="http://rubygems.org/gems/uuidtools"&gt;UUIDTools&lt;/a&gt; gem, whichever happens to be
available:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bnode = RDF::Node.uuid
bnode.to_s #=&amp;gt; "_:504c0a30-0d11-012d-3f50-001b63cac539"
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Working with &lt;a href="http://rdf.rubyforge.org/RDF/Literal.html"&gt;RDF::Literal&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All three types of RDF literals -- plain, language-tagged and datatyped --
are represented in RDF.rb as instances of the &lt;code&gt;RDF::Literal&lt;/code&gt; class.&lt;/p&gt;
&lt;h3&gt;Creating a plain literal&lt;/h3&gt;
&lt;p&gt;Create plain literals by passing in a string to the &lt;code&gt;RDF::Literal&lt;/code&gt;
constructor:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hello = RDF::Literal.new("Hello, world!")

hello.plain?         #=&amp;gt; true
hello.has_language?  #=&amp;gt; false
hello.has_datatype?  #=&amp;gt; false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note, however, that in most RDF.rb interfaces you will &lt;em&gt;not&lt;/em&gt; in fact need
to wrap language-agnostic, non-datatyped strings into &lt;code&gt;RDF::Literal&lt;/code&gt;
instances; this is done automatically when needed, allowing you the
convenience of, say, passing in a plain old Ruby string as the object value
when constructing an &lt;code&gt;RDF::Statement&lt;/code&gt; instance.&lt;/p&gt;
&lt;h3&gt;Creating a language-tagged literal&lt;/h3&gt;
&lt;p&gt;To create language-tagged literals, pass in an additional &lt;a href="http://en.wikipedia.org/wiki/ISO_639-1"&gt;ISO language
code&lt;/a&gt; to the &lt;code&gt;:language&lt;/code&gt; option of the &lt;code&gt;RDF::Literal&lt;/code&gt;
constructor:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hello = RDF::Literal.new("Hello!", :language =&amp;gt; :en)

hello.has_language?  #=&amp;gt; true
hello.language       #=&amp;gt; :en
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The language code can be given as either a symbol, a string, or indeed
anything that responds to the &lt;code&gt;#to_s&lt;/code&gt; method:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RDF::Literal.new("Hello!", :language =&amp;gt; :en)
RDF::Literal.new("Wazup?", :language =&amp;gt; :"en-US")
RDF::Literal.new("Hej!",   :language =&amp;gt; "sv")
RDF::Literal.new("&#161;Hola!", :language =&amp;gt; ["es"])
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Creating an explicitly datatyped literal&lt;/h3&gt;
&lt;p&gt;Datatyped literals are created similarly, by passing in a datatype URI to
the &lt;code&gt;:datatype&lt;/code&gt; option of the &lt;code&gt;RDF::Literal&lt;/code&gt; constructor:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;date = RDF::Literal.new("2010-12-31", :datatype =&amp;gt; RDF::XSD.date)

date.has_datatype?   #=&amp;gt; true
date.datatype        #=&amp;gt; RDF::XSD.date
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The datatype URI can be given as any object that responds to either the
&lt;code&gt;#to_uri&lt;/code&gt; method or the &lt;code&gt;#to_s&lt;/code&gt; method. In the example above, we've called
the &lt;code&gt;#date&lt;/code&gt; method on the &lt;code&gt;RDF::XSD&lt;/code&gt; vocabulary class which represents the
&lt;a href="http://en.wikipedia.org/wiki/XML_Schema_(W3C)"&gt;XML Schema&lt;/a&gt; datatypes vocabulary; this returns an &lt;code&gt;RDF::URI&lt;/code&gt; instance
representing the URI for the &lt;code&gt;xsd:date&lt;/code&gt; datatype.&lt;/p&gt;
&lt;h3&gt;Creating implicitly datatyped literals&lt;/h3&gt;
&lt;p&gt;You'll be glad to hear that you don't necessarily have to always explicitly
specify a datatype URI when creating a datatyped literal. RDF.rb supports a
degree of automatic mapping between Ruby classes and XML Schema datatypes.&lt;/p&gt;
&lt;p&gt;In most common cases, you can just pass in the Ruby value to the
&lt;code&gt;RDF::Literal&lt;/code&gt; constructor as-is, with the correct XML Schema datatype being
automatically set by RDF.rb:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;today = RDF::Literal.new(Date.today)

today.has_datatype?  #=&amp;gt; true
today.datatype       #=&amp;gt; RDF::XSD.date
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following implicit datatype mappings are presently supported by RDF.rb:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RDF::Literal.new(false).datatype               #=&amp;gt; RDF::XSD.boolean
RDF::Literal.new(true).datatype                #=&amp;gt; RDF::XSD.boolean
RDF::Literal.new(123).datatype                 #=&amp;gt; RDF::XSD.integer
RDF::Literal.new(9223372036854775807).datatype #=&amp;gt; RDF::XSD.integer
RDF::Literal.new(3.1415).datatype              #=&amp;gt; RDF::XSD.double
RDF::Literal.new(Date.new(2010)).datatype      #=&amp;gt; RDF::XSD.date
RDF::Literal.new(DateTime.new(2010)).datatype  #=&amp;gt; RDF::XSD.dateTime
RDF::Literal.new(Time.now).datatype            #=&amp;gt; RDF::XSD.dateTime
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Working with &lt;a href="http://rdf.rubyforge.org/RDF/Statement.html"&gt;RDF::Statement&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;RDF statements are represented in RDF.rb as instances of the
&lt;code&gt;RDF::Statement&lt;/code&gt; class. Statements can be &lt;em&gt;triples&lt;/em&gt; -- constituted of a
&lt;em&gt;subject&lt;/em&gt;, a &lt;em&gt;predicate&lt;/em&gt;, and an &lt;em&gt;object&lt;/em&gt; -- or they can be &lt;em&gt;quads&lt;/em&gt; that
also have an additional &lt;em&gt;context&lt;/em&gt; indicating the named graph that they are
part of.&lt;/p&gt;
&lt;h3&gt;Creating an RDF statement&lt;/h3&gt;
&lt;p&gt;Creating a triple works exactly as you'd expect:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;subject   = RDF::URI.new("http://rubygems.org/gems/rdf")
predicate = RDF::DC.creator
object    = RDF::URI.new("http://ar.to/#self")

RDF::Statement.new(subject, predicate, object)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The subject should be an &lt;code&gt;RDF::Resource&lt;/code&gt;, the predicate an &lt;code&gt;RDF::URI&lt;/code&gt;, and
the object an &lt;code&gt;RDF::Value&lt;/code&gt;. These constraints are not enforced, however,
allowing you to use any duck-typed equivalents as components of statements.&lt;/p&gt;
&lt;h3&gt;Creating an RDF statement with a context&lt;/h3&gt;
&lt;p&gt;Pass in a URI reference in an extra &lt;code&gt;:context&lt;/code&gt; option to the
&lt;code&gt;RDF::Statement&lt;/code&gt; constructor to create a quad:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;context   = RDF::URI.new("http://rubygems.org/")
subject   = RDF::URI.new("http://rubygems.org/gems/rdf")
predicate = RDF::DC.creator
object    = RDF::URI.new("http://ar.to/#self")

RDF::Statement.new(subject, predicate, object, :context =&amp;gt; context)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Creating an RDF statement from a hash&lt;/h3&gt;
&lt;p&gt;It's also worth mentioning that the &lt;code&gt;RDF::Statement&lt;/code&gt; constructor is
overloaded to enable instantiating statements from an options hash, as
follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RDF::Statement.new({
  :subject   =&amp;gt; RDF::URI.new("http://rubygems.org/gems/rdf"),
  :predicate =&amp;gt; RDF::DC.creator,
  :object    =&amp;gt; RDF::URI.new("http://ar.to/#self"),
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;:context&lt;/code&gt; option can also be given, as before. Use whichever method of
instantiating statements that you happen to prefer.&lt;/p&gt;
&lt;p&gt;Statement objects also support a &lt;code&gt;#to_hash&lt;/code&gt; method that provides the inverse
operation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;statement.to_hash   #=&amp;gt; { :subject   =&amp;gt; ...,
                    #     :predicate =&amp;gt; ..., 
                    #     :object    =&amp;gt; ... }
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Accessing RDF statement components&lt;/h3&gt;
&lt;p&gt;Access the RDF statement components -- the subject, the predicate, and the
object -- as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;statement.subject   #=&amp;gt; an RDF::Resource
statement.predicate #=&amp;gt; an RDF::URI
statement.object    #=&amp;gt; an RDF::Value
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since statements can also have an optional context, the following will
return either &lt;code&gt;nil&lt;/code&gt; or else an &lt;code&gt;RDF::Resource&lt;/code&gt; instance:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;statement.context   #=&amp;gt; an RDF::Resource or nil
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Working directly with triples and quads&lt;/h3&gt;
&lt;p&gt;Because RDF.rb is duck-typed, you can often directly use a three- or
four-item Ruby array in place of an &lt;code&gt;RDF::Statement&lt;/code&gt; instance. This can
sometimes feel less cumbersome than instantiating a statement object, and it
may also save some memory if you need to deal with a very large amount of
in-memory RDF statements. We'll see some examples of doing this this later
on.&lt;/p&gt;
&lt;p&gt;Converting from statement objects to Ruby arrays is trivial:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;statement.to_triple #=&amp;gt; [subject, predicate, object]
statement.to_quad   #=&amp;gt; [subject, predicate, object, context]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Likewise, instantiating a statement object from a triple represented as a
Ruby array is straightforward enough:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;RDF::Statement.new(*[subject, predicate, object])
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Working with &lt;a href="http://rdf.rubyforge.org/RDF/Graph.html"&gt;RDF::Graph&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;RDF graphs are represented in RDF.rb as instances of the &lt;code&gt;RDF::Graph&lt;/code&gt; class.
Note that most of the functionality in this class actually comes from the
&lt;code&gt;RDF::Enumerable&lt;/code&gt; and &lt;code&gt;RDF::Queryable&lt;/code&gt; mixins, which we'll examine further below.&lt;/p&gt;
&lt;h3&gt;Creating an anonymous graph&lt;/h3&gt;
&lt;p&gt;Creating a new unnamed graph works just as you'd expect:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph = RDF::Graph.new

graph.named? #=&amp;gt; false
graph.to_uri #=&amp;gt; nil
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Creating a named graph&lt;/h3&gt;
&lt;p&gt;To create a &lt;a href="http://www.w3.org/2004/03/trix/"&gt;named graph&lt;/a&gt;, just pass in a blank node or a URI
reference to the &lt;code&gt;RDF::Graph&lt;/code&gt; constructor:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph = RDF::Graph.new("http://rubygems.org/")

graph.named? #=&amp;gt; true
graph.to_uri #=&amp;gt; RDF::URI.new("http://rubygems.org/")
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Adding statements to a graph&lt;/h3&gt;
&lt;p&gt;To insert RDF statements into a graph, use the &lt;code&gt;#&amp;lt;&amp;lt;&lt;/code&gt; operator or the
&lt;code&gt;#insert&lt;/code&gt; method:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph &amp;lt;&amp;lt; statement

graph.insert(*statements)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let's add some RDF statements to an unnamed graph, taking advantage of the
aforementioned duck-typing convenience that lets us represent triples
directly using Ruby arrays, and plain literals directly using Ruby strings:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rdfrb = RDF::URI.new("http://rubygems.org/gems/rdf")
arto  = RDF::URI.new("http://ar.to/#self")

graph = RDF::Graph.new do
  self &amp;lt;&amp;lt; [rdfrb, RDF::DC.title,   "RDF.rb"]
  self &amp;lt;&amp;lt; [rdfrb, RDF::DC.creator, arto]
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you prefer, you can also be more explicit and use the equivalent
&lt;code&gt;#insert&lt;/code&gt; method form instead of the &lt;code&gt;#&amp;lt;&amp;lt;&lt;/code&gt; operator:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.insert([rdfrb, RDF::DC.title,   "RDF.rb"])
graph.insert([rdfrb, RDF::DC.creator, arto])
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Deleting statements from a graph&lt;/h3&gt;
&lt;p&gt;To delete RDF statements from a graph, use the &lt;code&gt;#delete&lt;/code&gt; method:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.delete(*statements)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Deleting the statements we inserted in the previous example works like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.delete([rdfrb, RDF::DC.title,   "RDF.rb"])
graph.delete([rdfrb, RDF::DC.creator, arto])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alternatively, we can use wildcard matching (where &lt;code&gt;nil&lt;/code&gt; stands for a
"match anything" wildcard) to simply delete every statement in the graph
that has a particular subject:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.delete([rdfrb, nil, nil])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For even more convenience, since non-existent array subscripts in Ruby
return &lt;code&gt;nil&lt;/code&gt;, the following abbreviation is exactly equivalent to the
previous example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.delete([rdfrb])
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Working with &lt;a href="http://rdf.rubyforge.org/RDF/Enumerable.html"&gt;RDF::Enumerable&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;RDF::Enumerable&lt;/code&gt; is a mixin module that provides RDF-specific iteration
methods for any object capable of yielding RDF statements.&lt;/p&gt;
&lt;p&gt;In what follows we will consider some of the key &lt;code&gt;RDF::Enumerable&lt;/code&gt; methods
specifically as used in instances of the &lt;code&gt;RDF::Graph&lt;/code&gt; class.&lt;/p&gt;
&lt;h3&gt;Checking whether any statements exist&lt;/h3&gt;
&lt;p&gt;Just as with most of Ruby's built-in collection classes, graphs support an
&lt;code&gt;#empty?&lt;/code&gt; predicate method that returns a boolean:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.empty?      #=&amp;gt; true or false
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Checking how many statements exist&lt;/h3&gt;
&lt;p&gt;You can use &lt;code&gt;#count&lt;/code&gt; -- or if you prefer, the equivalent alias &lt;code&gt;#size&lt;/code&gt; -- to
return the number of RDF statements in a graph:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.count
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Checking whether a specific statement exists&lt;/h3&gt;
&lt;p&gt;If you need to check whether a specific RDF statement is included in the
graph, use the following method:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.has_statement?(RDF::Statement.new(subject, predicate, object))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There also exists an otherwise equivalent convenience method that takes a
Ruby array as its argument instead of an &lt;code&gt;RDF::Statement&lt;/code&gt; instance:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.has_triple?([subject, predicate, object])
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Checking whether a specific value exists&lt;/h3&gt;
&lt;p&gt;If you need to check whether a particular value is included in the graph as
a component of one or more statements, use one of the following three
methods:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.has_subject?(RDF::URI.new("http://rdf.rubyforge.org/"))

graph.has_predicate?(RDF::DC.creator)

graph.has_object?(RDF::Literal.new("Hello!", :language =&amp;gt; :en))
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Enumerating all statements&lt;/h3&gt;
&lt;p&gt;The following method yields every statement in the graph as an
&lt;code&gt;RDF::Statement&lt;/code&gt; instance:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.each_statement do |statement|
  puts statement.inspect
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also use &lt;code&gt;#each&lt;/code&gt; as a shorter alias for &lt;code&gt;#each_statement&lt;/code&gt;, though we
ourselves consider using the more explicit form to be stylistically
preferred.&lt;/p&gt;
&lt;p&gt;If you don't require &lt;code&gt;RDF::Statement&lt;/code&gt; instances and simply want to get
directly at the triple components of statements, do the following instead:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.each_triple do |subject, predicate, object|
  puts [subject, predicate, object].inspect
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly, you can enumerate the graph using quads as well:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.each_quad do |subject, predicate, object, context|
  puts [subject, predicate, object, context].inspect
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that for unnamed graphs, the yielded &lt;code&gt;context&lt;/code&gt; will always be &lt;code&gt;nil&lt;/code&gt;;
for named graphs, it will always be the same &lt;code&gt;RDF::Resource&lt;/code&gt; instance as
would be returned by calling &lt;code&gt;graph.context&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Obtaining all statements&lt;/h3&gt;
&lt;p&gt;If instead of enumerating statements one-by-one you wish to obtain all the
data in a graph in one go as an array of statements, the following method
does just that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.statements  #=&amp;gt; [RDF::Statement(subject1, predicate1, object1), ...]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Naturally, there also exist the usual alternative methods that give you the
statements in the form of raw triples or quads represented as Ruby arrays:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.triples     #=&amp;gt; [[subject1, predicate1, object1], ...]
graph.quads       #=&amp;gt; [[subject1, predicate1, object1, context1], ...]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Enumerating all values&lt;/h3&gt;
&lt;p&gt;A particularly useful set of methods is the following, which yield unique
statement components from a graph:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.each_subject   { |value| puts value.inspect }
graph.each_predicate { |value| puts value.inspect }
graph.each_object    { |value| puts value.inspect }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For instance, &lt;code&gt;#each_subject&lt;/code&gt; yields every unique statement subject in the
graph, never yielding the same subject twice.&lt;/p&gt;
&lt;h3&gt;Obtaining all unique values&lt;/h3&gt;
&lt;p&gt;Again, instead of yielding unique values one-by-one, you can obtain them in
one go with the following methods:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.subjects    #=&amp;gt; [subject1, subject2, subject3, ...]
graph.predicates  #=&amp;gt; [predicate1, predicate2, predicate3, ...]
graph.objects     #=&amp;gt; [object1, object2, object3, ...]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, &lt;code&gt;#subjects&lt;/code&gt; returns an array containing all unique statement subjects
in the graph, and &lt;code&gt;#predicates&lt;/code&gt; and &lt;code&gt;#objects&lt;/code&gt; do the same for statement
predicates and objects respectively.&lt;/p&gt;
&lt;h2&gt;Working with &lt;a href="http://rdf.rubyforge.org/RDF/Queryable.html"&gt;RDF::Queryable&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;RDF::Queryable&lt;/code&gt; is a mixin that provides RDF-specific query methods for any
object capable of yielding RDF statements. At present this means simple
subject-predicate-object queries, but extended basic graph pattern matching
will be available in a future release of RDF.rb.&lt;/p&gt;
&lt;p&gt;In what follows we will consider &lt;code&gt;RDF::Queryable&lt;/code&gt; methods specifically as
used in instances of the &lt;code&gt;RDF::Graph&lt;/code&gt; class.&lt;/p&gt;
&lt;h3&gt;Querying for specific statements&lt;/h3&gt;
&lt;p&gt;The simplest type of query is one that specifies all statement components,
as in the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;statements = graph.query([subject, predicate, object])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result set here would contain either no statements if the query didn't
match (that is, the given statement didn't exist in the graph), or otherwise
at the most the single matched statement.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;#query&lt;/code&gt; method can also take a block, in which case matching statements
are yielded to the block one after another instead of returned as a result
set:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.query([subject, predicate, object]) do |statement|
  puts statement.inspect
end
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Querying with wildcard components&lt;/h3&gt;
&lt;p&gt;You can replace any of the query components with &lt;code&gt;nil&lt;/code&gt; to perform a
wildcard match. For example, in the following we query for all &lt;code&gt;dc:title&lt;/code&gt;
values for a given subject resource:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rdfrb = RDF::URI.new("http://rubygems.org/gems/rdf")

graph.query([rdfrb, RDF::DC.title, nil]) do |statement|
  puts "dc:title = #{statement.object.inspect}"
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also query for any and all statements related to a given subject
resource:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.query([rdfrb, nil, nil]) do |statement|
  puts "#{statement.predicate.inspect} = #{statement.object.inspect}"
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result sets returned by &lt;code&gt;#query&lt;/code&gt; also implement &lt;code&gt;RDF::Enumerable&lt;/code&gt; and
&lt;code&gt;RDF::Queryable&lt;/code&gt;, so it is possible to chain several queries to
incrementally refine a result set:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.query([rdfrb]).query([nil, RDF::DC.title])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Likewise, it is of course possible to chain &lt;code&gt;RDF::Queryable&lt;/code&gt; operations with
methods from &lt;code&gt;RDF::Enumerable&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;graph.query([nil, RDF::DC.title]).each_subject do |subject|
  puts subject.inspect
end
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The Mailing List&lt;/h2&gt;
&lt;p&gt;If you have feedback regarding RDF.rb, please contact us either
&lt;a href="http://github.com/datagraph"&gt;privately&lt;/a&gt; or via the
&lt;a href="http://lists.w3.org/Archives/Public/public-rdf-ruby/"&gt;public-rdf-ruby@w3.org&lt;/a&gt; mailing list. Bug reports should
go to the &lt;a href="http://github.com/bendiken/rdf/issues"&gt;issue queue&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;h2&gt;Coming Up&lt;/h2&gt;
&lt;p&gt;In upcoming RDF.rb tutorials we will see how to work with existing RDF
vocabularies, how to serialize and parse RDF data using RDF.rb, how to write
an RDF.rb plugin, how to use RDF.rb with &lt;a href="http://rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt; 3.0, and much
more. &lt;a href="http://feeds.feedburner.com/datagraph"&gt;Stay tuned&lt;/a&gt;!&lt;/p&gt;</description>
    <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-03-09T22:00:00Z</dc:date>
    <dc:creator>Arto Bendiken</dc:creator>
    <dc:subject>RDF</dc:subject>
    <dc:subject>Ruby</dc:subject>
    <dc:subject>RDF.rb</dc:subject>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </item>
  <item rdf:about="http://blog.datagraph.org/2010/03/grepping-ntriples">
    <title>RDF for Intrepid Unix Hackers: Grepping N-Triples</title>
    <link>http://blog.datagraph.org/2010/03/grepping-ntriples</link>
    <description>&lt;p&gt;The &lt;a href="http://en.wikipedia.org/wiki/N-Triples"&gt;N-Triples&lt;/a&gt; format is the lowest common denominator for &lt;a href="http://www.w3.org/RDF/"&gt;RDF&lt;/a&gt;
serialization formats, and turns out to be a very good fit to the Unix
paradigm of line-oriented, whitespace-separated data processing. In this
tutorial we'll see how to process N-Triples data by &lt;a href="http://en.wikipedia.org/wiki/Pipeline_(Unix)"&gt;pipelining&lt;/a&gt;
standard Unix tools such as &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;wc&lt;/code&gt;, &lt;code&gt;cut&lt;/code&gt;, &lt;code&gt;awk&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;, &lt;code&gt;uniq&lt;/code&gt;,
&lt;code&gt;head&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To follow along, you will need access to a Unix box (Mac OS X, Linux, or
BSD) with a &lt;a href="http://en.wikipedia.org/wiki/Bash"&gt;Bash&lt;/a&gt;-compatible shell. We'll be using &lt;a href="http://curl.haxx.se/"&gt;&lt;code&gt;curl&lt;/code&gt;&lt;/a&gt; to
fetch data over HTTP, but you can substitute &lt;code&gt;wget&lt;/code&gt; or &lt;code&gt;fetch&lt;/code&gt; if necessary. 
A couple of the examples require a modern &lt;a href="http://en.wikipedia.org/wiki/AWK"&gt;AWK&lt;/a&gt; version such as
&lt;a href="http://www.gnu.org/software/gawk/"&gt;&lt;code&gt;gawk&lt;/code&gt;&lt;/a&gt; or &lt;a href="http://invisible-island.net/mawk/mawk.html"&gt;&lt;code&gt;mawk&lt;/code&gt;&lt;/a&gt;; on Linux distributions you should be okay
by default, but on Mac OS X you will need to install &lt;code&gt;gawk&lt;/code&gt; or &lt;code&gt;mawk&lt;/code&gt; from
&lt;a href="http://www.macports.org/"&gt;MacPorts&lt;/a&gt; as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sudo port install mawk
$ alias awk=mawk
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="grokking_n-triples"&gt;Grokking N-Triples&lt;/h2&gt;
&lt;p&gt;Each N-Triples line encodes one RDF statement, also known as a &lt;em&gt;triple&lt;/em&gt;.
Each line consists of the subject (a URI or a blank node identifier), one or
more characters of whitespace, the predicate (a URI), some more whitespace,
and finally the object (a URI, blank node identifier, or literal) followed
by a dot and a newline. For example, the following N-Triples statement
asserts the title of my website:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;http://ar.to/&amp;gt; &amp;lt;http://purl.org/dc/terms/title&amp;gt; "Arto Bendiken" .
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is an almost perfect format for Unix tooling; the only possible further
improvement would have been to define the statement component separator to
be a tab character, which would have simplified obtaining the object
component of statements -- as we'll see in a bit.&lt;/p&gt;
&lt;h2 id="getting_n-triples"&gt;Getting N-Triples&lt;/h2&gt;
&lt;p&gt;Many RDF data dumps are made available as compressed N-Triples files.
&lt;a href="http://dbpedia.org/"&gt;DBpedia&lt;/a&gt;, the RDFization of Wikipedia, is a prominent example. For
purposes of this tutorial I've prepared an N-Triples dataset containing all
&lt;a href="http://drupal.org/"&gt;Drupal&lt;/a&gt;-related RDF statements from &lt;a href="http://wiki.dbpedia.org/Downloads34"&gt;DBpedia 3.4&lt;/a&gt;, which is the latest
release at the moment and reflects Wikipedia as of late September 2009.&lt;/p&gt;
&lt;p&gt;I prepared the sample dataset by downloading all English-language core
datasets (20 N-Triples files totaling 2.1 GB when compressed) and crunching
through them as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ bzgrep Drupal *.nt.bz2 &amp;gt; drupal.nt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To save you from gigabyte-sized downloads and an hour of data crunching, you
can just grab a copy of the resulting &lt;a href="http://blog.datagraph.org/2010/03/grepping-ntriples/drupal.nt"&gt;&lt;code&gt;drupal.nt&lt;/code&gt;&lt;/a&gt; file as
follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ curl http://blog.datagraph.org/2010/03/grepping-ntriples/drupal.nt &amp;gt; drupal.nt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The sample dataset totals 294 RDF statements and weighs in at 70 KB.&lt;/p&gt;
&lt;h2 id="counting_n-triples"&gt;Counting N-Triples&lt;/h2&gt;
&lt;p&gt;The first thing we want to do is count the number of triples in an N-Triples
dataset. This is straightforward to do, since each triple is represented by
one line in an N-Triples input file and there are a number of Unix tools
that can be used to count input lines. For example, we could use either of
the following commands:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cat drupal.nt | wc -l
294

$ cat drupal.nt | awk 'END { print NR }'
294
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we'll be using a lot more of &lt;a href="http://en.wikipedia.org/wiki/AWK"&gt;AWK&lt;/a&gt; throughout this tutorial, let's
stick with &lt;code&gt;awk&lt;/code&gt; and define a handy shell alias for this operation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias rdf-count="awk 'END { print NR }'"

$ cat drupal.nt | rdf-count
294
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that, for reasons of comprehensibility, the previous examples as well
as most of the subsequent ones assume that we're dealing with "clean"
N-Triples datasets that don't contain comment lines or other miscellania.
The DBpedia data dumps fit this bill very well. However, further onwards I
will give "fortified" versions of these commands that can correctly deal
with arbitrary N-Triples files.&lt;/p&gt;
&lt;h2 id="measuring_n-triples"&gt;Measuring N-Triples&lt;/h2&gt;
&lt;p&gt;We at Datagraph frequently use the N-Triples representation as the canonical
lexical form of an RDF statement, and work with &lt;a href="http://rdfcache.rubyforge.org/"&gt;content-addressable storage
systems for RDF data&lt;/a&gt; that in fact &lt;em&gt;store&lt;/em&gt; statements using their
N-Triples representation. In such cases, it is often useful to know some
statistical characteristics of the data to be loaded in a mass import, so as
to e.g. be able to fine-tune the underlying storage for optimum space
efficiency.&lt;/p&gt;
&lt;p&gt;A first useful statistic is to know the typical size of a datum, i.e. the
line length of an N-Triples statement, in the dataset we're dealing with.
AWK yields us N-Triples line lengths without much trouble:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias rdf-lengths="awk '{ print length }'"

$ cat drupal.nt | rdf-lengths | head -n5
162
150
155
137
150
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that N-Triples is an ASCII format, so the numbers above reflect both
the byte sizes of input lines as well as the ASCII character count of input
lines. All non-ASCII characters are escaped in N-Triples, and for present
purposes we'll be talking in terms of ASCII characters only.&lt;/p&gt;
&lt;p&gt;The above list of line lengths in and of itself won't do us much good; we
want to obtain aggregate information for the whole dataset at hand, not for
individual statements. It's too bad that Unix doesn't provide commands for
simple numeric aggregate operations such as the minimum, maximum and average
of a list of numbers, so let's see if we can remedy that.&lt;/p&gt;
&lt;p&gt;One way to define such operations would be to pipe the above output to an
&lt;a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation"&gt;RPN&lt;/a&gt; shell calculator such as &lt;code&gt;dc&lt;/code&gt; and have it perform the needed
calculations. The complexity of this would go somewhat beyond mere shell
aliases, however. Thankfully, it turns out that AWK is well-suited to
writing these aggregate operations as well. Here's how we can extend
our earlier pipeline to boil the list of line lengths down to an average:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias avg="awk '{ s += \$1 } END { print s / NR }'"

$ cat drupal.nt | rdf-lengths | avg
242.517
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above, incidentally, is an example of a simple &lt;a href="http://en.wikipedia.org/wiki/MapReduce"&gt;map/reduce&lt;/a&gt;
operation: a sequence of input values is &lt;em&gt;mapped&lt;/em&gt; through a function, in
this case &lt;code&gt;length(line)&lt;/code&gt;, to give a sequence of output values (the line
lengths) that is then &lt;em&gt;reduced&lt;/em&gt; to a single aggregate value (the average
line length). Though I won't go further into this just now, it is worth
mentioning in passing that N-Triples is an ideal format for massively
parallel processing of RDF data using &lt;a href="http://hadoop.apache.org/"&gt;Hadoop&lt;/a&gt; and the like.&lt;/p&gt;
&lt;p&gt;Now, we can still optimize and simplify the above some by combining both
steps of the operation into a single alias that outputs an average line
length for the given input stream, like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias rdf-length-avg="awk '\
  { s += length }
  END { print s / NR }'"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Likewise, it doesn't take much more to define an alias for obtaining the
maximum line length in the input dataset:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias rdf-length-max="awk '\
  BEGIN { n = 0 } \
  { if (length &amp;gt; n) n = length } \
  END { print n }'"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Getting the minimum line length is only slightly more complicated. Instead
of comparing against a zero baseline like above, we need to instead define a
"roof" value to compare against. In the following, I've picked an
arbitrarily large number, making the (at present) reasonable assumption that
no N-Triples line will be longer than a billion ASCII characters, which
would amount to somewhat less than a binary gigabyte:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias rdf-length-min="awk '\
  BEGIN { n = 1e9 } \
  { if (length &amp;gt; 0 &amp;amp;&amp;amp; length &amp;lt; n) n = length } \
  END { print (n &amp;lt; 1e9 ? n : 0) }'"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that we have some aggregate operations to crunch N-Triples data with,
let's analyze our sample DBpedia dataset using the three aliases defined
above:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cat drupal.nt | rdf-length-avg
242.517

$ cat drupal.nt | rdf-length-max
2179

$ cat drupal.nt | rdf-length-min
84
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see from the output that N-Triples line lengths in this dataset vary
considerably: from less than a hundred bytes to several kilobytes, but being
on average in the range of two hundred bytes. This variability is to be
expected for DBpedia data, given that many RDF statements in such a dataset
contain a long textual description as their object literal whereas others
contain merely a simple integer literal.&lt;/p&gt;
&lt;p&gt;Many other statistics, such as the median line length or the standard
deviation of the line lengths, could conceivably be obtained in a manner
similar to what I've shown above. I'll leave those as exercises for the
reader, however, as further stats regarding the raw N-Triples lines are
unlikely to be all that generally interesting.&lt;/p&gt;
&lt;h2 id="parsing_n-triples"&gt;Parsing N-Triples&lt;/h2&gt;
&lt;p&gt;It's time to move on to getting at the three components -- the subject, the
predicate and the object -- that constitute RDF statements.&lt;/p&gt;
&lt;p&gt;We have two straightforward choices for obtaining the subject and predicate:
the &lt;code&gt;cut&lt;/code&gt; command and good old &lt;code&gt;awk&lt;/code&gt;. I'll show both aliases:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias rdf-subjects="cut -d' ' -f 1 | uniq"
$ alias rdf-subjects="awk '{ print \$1 }' | uniq"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While &lt;code&gt;cut&lt;/code&gt; might shave off some microseconds compared to &lt;code&gt;awk&lt;/code&gt; here, AWK is
still the better choice for the general case, as it allows us to expand the
alias definition to ignore empty lines and comments, as we'll see later. On
our sample data, though, either form works fine.&lt;/p&gt;
&lt;p&gt;You may have noticed and wondered about the pipelined &lt;code&gt;uniq&lt;/code&gt; after &lt;code&gt;cut&lt;/code&gt; and
&lt;code&gt;awk&lt;/code&gt;. This is simply a low-cost, low-grade deduplication filter: it drops
consequent duplicate values. For an ordered dataset (where the input
N-Triples lines are already sorted in lexical order), it will get rid of all
duplicate subjects. In an unordered dataset, it won't do much good, but it
won't do much harm either (what's a microsecond here or there?)&lt;/p&gt;
&lt;p&gt;To fully deduplicate the list of subjects for a (potentially) unordered
dataset, apply another &lt;code&gt;uniq&lt;/code&gt; filter after a &lt;code&gt;sort&lt;/code&gt; operation as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cat drupal.nt | rdf-subjects | sort | uniq | head -n5
&amp;lt;http://dbpedia.org/resource/Acquia_Drupal&amp;gt;
&amp;lt;http://dbpedia.org/resource/Adland&amp;gt;
&amp;lt;http://dbpedia.org/resource/Advomatic&amp;gt;
&amp;lt;http://dbpedia.org/resource/Apadravya&amp;gt;
&amp;lt;http://dbpedia.org/resource/Application_programming_interface&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I've not made &lt;code&gt;sort&lt;/code&gt; an integral part of the &lt;code&gt;rdf-subjects&lt;/code&gt; alias because
sorting the subjects is an expensive operation with resource usage
proportional to the number of statements processed; when processing a
billion-triple N-Triples stream, it is usually simply better to not care too
much about ordering.&lt;/p&gt;
&lt;p&gt;Getting the predicates from N-Triples data works exactly the same way as
getting the subjects:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias rdf-predicates="cut -d' ' -f 2 | uniq"
$ alias rdf-predicates="awk '{ print \$2 }' | uniq"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, you can apply &lt;code&gt;sort&lt;/code&gt; in conjunction  with &lt;code&gt;uniq&lt;/code&gt; to get the list of
unique predicate URIs in the dataset:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cat drupal.nt | rdf-predicates | sort | uniq | tail -n5
&amp;lt;http://www.w3.org/2000/01/rdf-schema#label&amp;gt;
&amp;lt;http://www.w3.org/2004/02/skos/core#subject&amp;gt;
&amp;lt;http://xmlns.com/foaf/0.1/depiction&amp;gt;
&amp;lt;http://xmlns.com/foaf/0.1/homepage&amp;gt;
&amp;lt;http://xmlns.com/foaf/0.1/page&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Obtaining the object component of N-Triples statements, however, is somewhat more
complicated than getting the subject or the predicate. This is due to the
fact that object literals can contain whitespace that will throw off the
whitespace-separated field handling of &lt;code&gt;cut&lt;/code&gt; and &lt;code&gt;awk&lt;/code&gt; that we've relied on
so far. Not to worry, AWK can still get us the results we want, but I won't
attempt to explain how the following alias works; just be happy that it
does:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias rdf-objects="awk '{ ORS=\"\"; for (i=3;i&amp;lt;=NF-1;i++) print \$i \" \"; print \"\n\" }' | uniq"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output of &lt;code&gt;rdf-objects&lt;/code&gt; is the N-Triples encoded object URI, blank node
identifier or object literal. URIs are output in the same format as
subjects and predicates, with enclosing angle brackets; language-tagged
literals include the language tag, and datatyped literals include the
datatype URI:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cat drupal.nt | rdf-objects | sort | uniq | head -n5
"09"^^&amp;lt;http://www.w3.org/2001/XMLSchema#integer&amp;gt;
"16"^^&amp;lt;http://www.w3.org/2001/XMLSchema#integer&amp;gt;
"2001-01"^^&amp;lt;http://www.w3.org/2001/XMLSchema#gYearMonth&amp;gt;
"2009"^^&amp;lt;http://www.w3.org/2001/XMLSchema#integer&amp;gt;
"6.14"^^&amp;lt;http://www.w3.org/2001/XMLSchema#decimal&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another very useful operation to have is getting the list of object literal
datatypes used in an N-Triples dataset. This is also a somewhat involved
alias definition, and requires a modern AWK version such as &lt;a href="http://www.gnu.org/software/gawk/"&gt;&lt;code&gt;gawk&lt;/code&gt;&lt;/a&gt;
or &lt;a href="http://invisible-island.net/mawk/mawk.html"&gt;&lt;code&gt;mawk&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias rdf-datatypes="awk -F'\x5E' '/\"\^\^&amp;lt;/ { print substr(\$3, 1, length(\$3)-2) }' | uniq"

$ cat drupal.nt | rdf-datatypes | sort | uniq
&amp;lt;http://www.w3.org/2001/XMLSchema#decimal&amp;gt;
&amp;lt;http://www.w3.org/2001/XMLSchema#gYearMonth&amp;gt;
&amp;lt;http://www.w3.org/2001/XMLSchema#integer&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we can see, most object literals in this dataset are untyped strings, but
there are some decimal and integer values as well as year + month literals.&lt;/p&gt;
&lt;h2 id="aliasing_n-triples"&gt;Aliasing N-Triples&lt;/h2&gt;
&lt;p&gt;As promised, here follow more robust versions of all the aforementioned Bash
aliases. Just copy and paste the following code snippet into your
&lt;code&gt;~/.bash_aliases&lt;/code&gt; or &lt;code&gt;~/.bash_profile&lt;/code&gt; file, and you will always have these
aliases available when working with N-Triples data on the command line.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# N-Triples aliases from http://blog.datagraph.org/2010/03/grepping-ntriples
alias rdf-count="awk '/^\s*[^#]/ { n += 1 } END { print n }'"
alias rdf-lengths="awk '/^\s*[^#]/ { print length }'"
alias rdf-length-avg="awk '/^\s*[^#]/ { n += 1; s += length } END { print s/n }'"
alias rdf-length-max="awk 'BEGIN { n=0 } /^\s*[^#]/ { if (length&amp;gt;n) n=length } END { print n }'"
alias rdf-length-min="awk 'BEGIN { n=1e9 } /^\s*[^#]/ { if (length&amp;gt;0 &amp;amp;&amp;amp; length&amp;lt;n) n=length } END { print (n&amp;lt;1e9 ? n : 0) }'"
alias rdf-subjects="awk '/^\s*[^#]/ { print \$1 }' | uniq"
alias rdf-predicates="awk '/^\s*[^#]/ { print \$2 }' | uniq"
alias rdf-objects="awk '/^\s*[^#]/ { ORS=\"\"; for (i=3;i&amp;lt;=NF-1;i++) print \$i \" \"; print \"\n\" }' | uniq"
alias rdf-datatypes="awk -F'\x5E' '/\"\^\^&amp;lt;/ { print substr(\$3, 2, length(\$3)-4) }' | uniq"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I should also note that though I've spoken throughout only in terms of
N-Triples, most of the above aliases will work fine also for input in
&lt;a href="http://sw.deri.org/2008/07/n-quads/"&gt;N-Quads&lt;/a&gt; format.&lt;/p&gt;
&lt;p&gt;In the next installments of &lt;em&gt;RDF for Intrepid Unix Hackers&lt;/em&gt;, we'll attempt
something a little more ambitious: building a &lt;code&gt;rdf-query&lt;/code&gt; alias to perform
subject-predicate-object queries on N-Triples input. We'll also see
&lt;a href="http://blog.datagraph.org/2010/04/transmuting-ntriples"&gt;what to do if your RDF data isn't already in N-Triples format&lt;/a&gt;,
learning how to install and use the &lt;a href="http://librdf.org/raptor/"&gt;Raptor RDF Parser Library&lt;/a&gt; to
convert RDF data between the various popular RDF serialization formats. 
&lt;a href="http://feeds.feedburner.com/datagraph"&gt;Stay tuned&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;small&gt;&lt;em&gt;Lest there be any doubt, all the code in this tutorial is hereby
released into the public domain using the &lt;a href="http://unlicense.org/"&gt;Unlicense&lt;/a&gt;. You are free to
copy, modify, publish, use, sell and distribute it in any way you please,
with or without attribution.&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;</description>
    <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-03-04T16:00:00Z</dc:date>
    <dc:creator>Arto Bendiken</dc:creator>
    <dc:subject>RDF</dc:subject>
    <dc:subject>Unix</dc:subject>
    <dc:subject>AWK</dc:subject>
    <dc:subject>N-Triples</dc:subject>
    <dc:subject>DBpedia</dc:subject>
    <dc:subject>Drupal</dc:subject>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </item>
  <item rdf:about="http://blog.datagraph.org/2010/02/hacking-rdf-in-ruby">
    <title>Hacking on RDF in Ruby</title>
    <link>http://blog.datagraph.org/2010/02/hacking-rdf-in-ruby</link>
    <description>&lt;p&gt;&lt;a href="http://rubygems.org/gems/rdf"&gt;RDF.rb&lt;/a&gt; is easily the most fun RDF
library I've used.  It uses Ruby's dynamic system of mixins to create
a library that's very easy to use.&lt;/p&gt;
&lt;p&gt;If you're new at Ruby, you might know about mixins in other
languages--&lt;a href="http://www.scala-lang.org/node/126"&gt;Scala traits&lt;/a&gt;, for
example, are almost exactly functionally equivalent.  They're
distinctly more powerful than Java interfaces or abstract classes.  A
mixin is basically an interface and an abstract class rolled into one.
 Rather than extend an abstract class, one includes a mixin into your
own class.  A mixin will usually require that a given class implement
a particular method.  Ruby's own &lt;code&gt;Enumerable&lt;/code&gt; class, for example,
requires that implementing classes implement &lt;code&gt;#each&lt;/code&gt;.  For that tiny
bit of trouble, you get a ton of methods (listed
&lt;a href="http://ruby-doc.org/core/classes/Enumerable.html"&gt;here&lt;/a&gt;), including
iterators, mapping, partitions, conversion to arrays, and more.  (If
you're new to Ruby, it might also help you to know that &lt;code&gt;#method_name&lt;/code&gt;
means 'an instance method named &lt;code&gt;method_name&lt;/code&gt;').&lt;/p&gt;
&lt;p&gt;RDF.rb uses the principle extensively.  &lt;code&gt;RDF::Repository&lt;/code&gt; is, in fact,
little more than an in-memory reference implementation for 4 traits:
&lt;code&gt;RDF::Enumerable&lt;/code&gt;, &lt;code&gt;RDF::Mutable&lt;/code&gt;, &lt;code&gt;RDF::Queryable&lt;/code&gt;, and
&lt;code&gt;RDF::Durable&lt;/code&gt;.  &lt;code&gt;RDF::Sesame::Repository&lt;/code&gt; has the exact same
interface as the in-memory representation, but is based entirely on a
Sesame server.  In order to work as a repository,
&lt;code&gt;RDF::Sesame::Repository&lt;/code&gt; only had to extend the reference
implementation and implement &lt;code&gt;#each&lt;/code&gt;, &lt;code&gt;#insert_statement&lt;/code&gt;, and
&lt;code&gt;#delete_statement&lt;/code&gt;.  Nice!  Of course, implementing those took some
doing, but it's still exceedingly easy.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://rdf.rubyforge.org/RDF/Enumerable.html"&gt;&lt;code&gt;RDF::Enumerable&lt;/code&gt;&lt;/a&gt; is
the key here.  For implementing an &lt;code&gt;#each&lt;/code&gt; that yields
&lt;code&gt;RDF::Statement&lt;/code&gt; objects, one gains a ton of functionality:  &lt;code&gt;#each_subject&lt;/code&gt;,
&lt;code&gt;#each_predicate&lt;/code&gt;, &lt;code&gt;#each_object&lt;/code&gt;, &lt;code&gt;#each_context&lt;/code&gt;, &lt;code&gt;#has_subject?&lt;/code&gt;,
&lt;code&gt;#has_triple?&lt;/code&gt;, and more.  It's a key abstraction that provides huge
amounts of functionality.&lt;/p&gt;
&lt;p&gt;But the module system goes the other way--not only is it easy to
implement new RDF models, existing ones are easily extended.  I
recently wrote &lt;a href="http://github.com/bhuga/RDF-Isomorphic"&gt;&lt;code&gt;RDF::Isomorphic&lt;/code&gt;&lt;/a&gt;,
which extends RDF::Enumerable with &lt;code&gt;#bijection_to&lt;/code&gt; and
&lt;code&gt;#isomorphic_with?&lt;/code&gt; methods.  The module-based system provided by
RDF.rb means that my isomorphic methods are now available on
&lt;code&gt;RDF::Sesame::Repositories&lt;/code&gt;, and indeed anything which includes
&lt;code&gt;RDF::Enumerable&lt;/code&gt;.  This is everything from repositories to graphs to
query results!  In fact, query results themselves implement
&lt;code&gt;RDF::Enumerable&lt;/code&gt;, and thus implement &lt;code&gt;RDF::Queryable&lt;/code&gt; and can be
checked for isomorphism, or whatever else you want to add.  This is
functionality that Sesame does not have natively, and which I wrote
for a completely different purpose (testing parsers).  Every
&lt;code&gt;RDF::Enumerable&lt;/code&gt; gets it for free because I wanted to compare 2 textual
formats.  Neat!&lt;/p&gt;
&lt;p&gt;For example, here's what it takes to extend any RDF collection, from
&lt;code&gt;RDF::Isomorphic&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'rdf'
module RDF
  ##
  # Isomorphism for RDF::Enumerables
  module Isomorphic

    def isomorphic_with(other)
      # code that uses #each, or any other method from RDF::Enumerable goes here
      ...
    end

    def bijection_to(other)
      # code that uses #each, or any other method from RDF::Enumerable goes here
         ...
    end
  end

  # re-open RDF::Enumerable and add the isomorphic methods
  module Enumerable
    include RDF::Isomorphic
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course, this just can't be done without &lt;a href="http://en.wikipedia.org/wiki/Monkey_patch"&gt;monkey
patching.&lt;/a&gt;  Mixins and
monkey patching together make for a powerful toolkit.  To my
knowledge, this is the first RDF library that takes advantage of these
features.&lt;/p&gt;
&lt;p&gt;It's possible to provide powerful features to a wide range of
implementations with this.  RDF.rb does not yet have a inference
layer, but any such layer would instantly work for any store which
implements &lt;code&gt;RDF::Enumerable&lt;/code&gt;.  Want to prototype some custom business
logic that operates over existing RDF data?  Copy it into a local
repository and hack away.  No need for the production RDF store to be
the same at all, but you can still apply the same code.&lt;/p&gt;
&lt;p&gt;As a counter-example, compare this to the Java RDF ecosystem.  There
are some excellent implementations (&lt;code&gt;RDF::Isomorphic&lt;/code&gt; is heavily in
debt to Jena), but they're all incompatible.  Jena's check for
isomorphism is not really translatable to Sesame, or anything else.
RDF.rb, in addition to providing a reference implementation, acts as
an abstraction layer for underlying RDF implementations.  The
difference is night and day--with RDF.rb, you only need to implement a
feature once, at the API layer, to have it apply to any
implementation.  This is not a knock at the very talented people
behind those Java implementations; making this happen is a lot of work
in a language without monkey patching, and RDF.rb is only as good as
it is because of the significant influences those projects have been
on &lt;a href="http://ar.to"&gt;Arto's&lt;/a&gt; design.&lt;/p&gt;
&lt;p&gt;The end result of the mixin-based approach is a system that is
incredibly easy to extend, and just downright fun.  It would be a
fairly simple task to extend a Ruby class completely unrelated to RDF
with an &lt;code&gt;#each&lt;/code&gt; method that yields statements, allowing it to work in
&lt;a href="http://rdf.rubyforge.org/RDF/Enumerable.html"&gt;&lt;code&gt;RDF::Enumerable&lt;/code&gt;&lt;/a&gt;.
Voila, your existing classes now have an RDF representation.  Along
the same lines, if one is bothered by the statement-oriented nature of
RDF.rb, building a system which took a resource-oriented view would
not require one to 'break away' from the RDF.rb ecosystem.  Just build
your subject-oriented model objects and implement &lt;code&gt;#each&lt;/code&gt;, and away you
go--you can now run RDF queries and test isomorphism on your model.
Build it to accept an &lt;code&gt;RDF::Enumerable&lt;/code&gt; in the constructor and you can
use any existing repository or query to initialize your model.&lt;/p&gt;
&lt;p&gt;RDF.rb is not yet ready for production use, but it's under heavy
development and already quite useful.  Give it a shot.  You can post
any issues in the &lt;a href="http://github.com/bendiken/rdf/issues"&gt;GitHub issue
queue&lt;/a&gt;.&lt;/p&gt;</description>
    <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-02-28T07:20:17Z</dc:date>
    <dc:creator>Ben Lavender</dc:creator>
    <dc:subject>Ruby</dc:subject>
    <dc:subject>RDF</dc:subject>
    <dc:subject>RDF.rb</dc:subject>
    <dc:subject>RDF::Isomorphic</dc:subject>
    <dc:source rdf:resource="http://bhuga.net/2010/02/hacking-rdf-ruby"/>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </item>
  <item rdf:about="http://blog.datagraph.org/2010/02/jquery-with-rails-3">
    <title>Using jQuery with Rails 3.0 Beta</title>
    <link>http://blog.datagraph.org/2010/02/jquery-with-rails-3</link>
    <description>&lt;p&gt;One of the most talked about features in Rails 3 is its plug &amp;amp; play architecture with various frameworks like Datamapper in place of ActiveRecord for the ORM or jQuery for javascript.  However, I've yet to see much info on how to actually do this with the javascript framework.&lt;/p&gt;
&lt;p&gt;Fortunately, it looks like a lot of the hard work has already been done.  Rails now emits HTML that is compatible with the unobtrusive approach to javascript.  Meaning, instead of seeing a delete link like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;a href="/users/1" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);f.submit(); };return false;"&amp;gt;Delete&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;you'll now see it written as&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;a rel="nofollow" data-method="delete" data-confirm="Are you sure?" class="delete" href="/user/1"&amp;gt;Delete&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This makes it very easy for a javascript driver to come along, pick out and identify the relevant pieces, and attach the appropriate handlers.&lt;/p&gt;
&lt;p&gt;So, enough blabbing.  How do you get jQuery working with Rails 3?  I'll try to make this short and sweet.&lt;/p&gt;
&lt;p&gt;Grab the jQuery driver at &lt;a href="http://github.com/rails/jquery-ujs"&gt;http://github.com/rails/jquery-ujs&lt;/a&gt; and put it in your javascripts directory.  The file is at src/rails.js&lt;/p&gt;
&lt;p&gt;Include jQuery (I just use the google hosted version) and the driver in your application layout or view.  In HAML it would look something like.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"
= javascript_include_tag 'rails'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rails requires an authenticity token to do form posts back to the server.  This helps protect your site against CSRF attacks.  In order to handle this requirement the driver looks for two meta tags that must be defined in your page's head. This would look like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;meta name="csrf-token" content="&amp;lt;%= form_authenticity_token %&amp;gt;" /&amp;gt;
&amp;lt;meta name="csrf-param" content="authenticity_token" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In HAML this would be:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;%meta{:name =&amp;gt; 'csrf-token', :content =&amp;gt; form_authenticity_token}
%meta{:name =&amp;gt; 'csrf-param', :content =&amp;gt; 'authenticity_token'}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Jeremy Kemper points out that the above meta tags can written out with a single call to "csrf_meta_tag".&lt;/p&gt;
&lt;p&gt;That should be all you need.  Remember, this is still a work in progress, so don't be surprised if there's a few bugs.  Please also note this has been tested with Rails 3.0.0.beta.&lt;/p&gt;</description>
    <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2010-02-08T22:04:52Z</dc:date>
    <dc:creator>Josh Huckabee</dc:creator>
    <dc:subject>jQuery</dc:subject>
    <dc:subject>Ruby on Rails</dc:subject>
    <dc:subject>JavaScript</dc:subject>
    <dc:subject>Ruby</dc:subject>
    <dc:source rdf:resource="http://joshhuckabee.com/jquery-rails-3"/>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </item>
  <item rdf:about="http://blog.datagraph.org/2009/11/sparql-1.1-critique">
    <title>Is W3C Going the Wrong Direction with SPARQL 1.1?</title>
    <link>http://blog.datagraph.org/2009/11/sparql-1.1-critique</link>
    <description>&lt;p&gt;The &lt;a href="http://www.w3.org/2001/sw/DataAccess/"&gt;W3C SPARQL working group&lt;/a&gt;  (previously the Data Access Working Group) has recently released their &lt;a href="http://www.w3.org/2009/sparql/wiki/Main_Page"&gt;first versions of the updated SPARQL standards&lt;/a&gt;, or SPARQL 1.1.  The group's &lt;a href="http://www.w3.org/2009/05/sparql-phase-II-charter#milestones"&gt;roadmap&lt;/a&gt; has these finalized a year from now, but they have asked for comments and I suppose these are mine.&lt;/p&gt;

&lt;p&gt;I believe that these documents are a step further down a wrong path for SPARQL and, to a lesser degree, for RDF in general.&lt;/p&gt;

&lt;p&gt;The latest round of changes includes a number of changes to SPARQL, including &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-query-20091022/#aggregateFunctions"&gt;aggregate functions&lt;/a&gt;, &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-query-20091022/#subqueries"&gt;subqueries&lt;/a&gt;, &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-query-20091022/#projectExpressions"&gt;projection expressions&lt;/a&gt;, &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-query-20091022/#negation"&gt;negations&lt;/a&gt;, &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-update-20091022/"&gt;updates and deletions&lt;/a&gt;, &lt;a href="http://www.w3.org//TR/2009/WD-sparql11-protocol-20091022/#query-bindings-http"&gt;more specific HTTP protocol bindings&lt;/a&gt;, &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-service-description-20091022/"&gt;service discovery&lt;/a&gt;, &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-entailment-20091022/"&gt;entailment regimes&lt;/a&gt;, and a &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-http-rdf-update-20091022/"&gt;RESTful protocol for managing RDF graphs&lt;/a&gt; (the last one is not really just SPARQL, but it's in the updates).&lt;/p&gt;

&lt;p&gt;So I'll start with my comments, which are mostly critical.&lt;/p&gt;

&lt;p&gt;To start, an RDF-specific complaint, not really related to the rest of the post.  Why would the one &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-http-rdf-update-20091022/#protocol-model"&gt;mandated format to be supported in the new RESTful RDF graph management interface&lt;/a&gt; be RDF/XML?  What would it take for a the semweb community to move on from this failed standard, which has had &lt;a href="http://www.w3.org/2000/03/rdf-tracking/#rdfms-qnames-cant-represent-all-uris"&gt;known&lt;/a&gt; &lt;a href="http://www.w3.org/2000/03/rdf-tracking/#rdfms-syntax-incomplete"&gt;issues&lt;/a&gt; for more than 5 years? (those two issues were raised in 2001 and are currently marked 'postponed')  Why should such an increasingly irrelevant standard as RDF/XML be chosen instead of the widely-supported and easy to implement N3, N-Triples, or Turtle?&lt;/p&gt;

&lt;p&gt;As for SPARQL, the 1.1 standards continue to give named graphs first class citizen status, both in the web APIs and in &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-update-20091022/#sec_examples"&gt;more SPARQL syntax&lt;/a&gt; than they had before.  It's not so much triples as quads these days.  Other meta-metadata, such as time of assertion or validity time, are not covered.  While named graphs are admittedly a particularly often-found case, why does it need to invade the syntax of SPARQL?  Not every use case needs named graphs, but every SPARQL implementor must support them.  The 1.1 standard now includes &lt;a href="http://www.w3.org//TR/2009/WD-sparql11-protocol-20091022/#select-ambiguous"&gt;precedence rules&lt;/a&gt; when for named graph and base URIs when they conflict in HTTP query options and inside the query itself, attempting to solve this self-created problem.&lt;/p&gt;

&lt;p&gt;How about &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-query-20091022/#subqueries"&gt;subqueries&lt;/a&gt;?  What about &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-update-20091022/#t515"&gt;variables during insertions&lt;/a&gt;?  What about &lt;a href="http://www.w3.org/TR/2009/WD-sparql11-update-20091022/#d4e190"&gt;subqueries during insertions&lt;/a&gt;?  Do we really need implementors to consider these kinds of things for every SPARQL endpoint on the web?&lt;/p&gt;

&lt;p&gt;None of these things is really all that bad by itself, but one must consider the bigger picture.  SPARQL 1.0 was released in January of 2008 (with some comment period before that) and there is still no implementation of a SPARQL engine in PHP or Ruby (exceptions apply, see [1]).  One does not increase the participation of that ecosystem by adding a selection of entailment regimes to the standard.&lt;/p&gt;

&lt;p&gt;While a SPARQL implementation exists for the excellent &lt;a href="http://www.rdflib.net/"&gt;RDFLib&lt;/a&gt; in Python, it's only one of the current big 3 (with Ruby and PHP) in web development, and there's only one.  The fact that no SPARQL engines exist for Ruby or PHP should be considered a failure of the standard.  Why are we adding complexity when there is no SQLite for SPARQL?  Why are there at least 3 monolithic Java implementations (Jena, Sesame, Boca), all financially sponsored to some degree or another, but so little 'in the wild'?  How long can RDFLib herd 16 cats as &lt;a href="http://code.google.com/p/rdflib/people/list"&gt;committers on the project&lt;/a&gt;?  While I don't have a lot of direct experience with RDFLib, I pity the project 'leads' (I cannot find evidence that the project is sponsored or that anyone is 'in charge') trying to look towards the future of implementing 6 working papers of new standards.&lt;/p&gt;

&lt;p&gt;One of the biggest success stories for semweb in widespread use is the &lt;a href="http://drupal.org/project/rdf"&gt;Drupal RDF module&lt;/a&gt;, which has found wide acceptance in the Drupal community and started an ecosystem of modules.  Drupal 7 will output &lt;a href="http://api.drupal.org/api/group/rdf/7"&gt;RDFa by default&lt;/a&gt; and Drupal 6 supports a ton of wonderful features, including &lt;a href="http://ar.to/2009/03/rdfizing-drupal-rss-feeds"&gt;reversing the RSS 1.0 to 2.0 downgrade back to RDF&lt;/a&gt;.  But Drupal remains a producer of simple triples and a consumer of SPARQL queries generated by other endpoints.  Data in those sites remains locked down.  Why?  Because implementing SPARQL in PHP is nontrivial, and in a chicken-egg problem, nobody's paying for it before someone has a need for SPARQL.&lt;/p&gt;

&lt;p&gt;I could go on, but these are symptoms (well, not that RDF/XML thing, I don't think there's a good reason for that).  I feel that the working group is attempting to solve the wrong problem.  Namely, it is attempting to define a somewhat-human-readable query language, SPARQL that works for almost all use cases.  But why must the whole 'kitchen sink' be well-defined?  Such a standards body should be attempting to define the easiest possible thing to implement and extend, not the the last tool anyone would ever use.&lt;/p&gt;

&lt;p&gt;The SPARQL 1.0 standard's grammar was well-defined as a context free grammar.  It also had extension functions, which were uniquely defined by URIs.  Why the distinction between CFG elements and extension functions?  Why not make syntax elements like named graphs and aggregate functions as discoverable as extensions?  Well, the reason is that it's hard to write a parser of a human-readable format and make those things optional and discoverable.  (&lt;a href="http://github.com/datagraph/datagraph-sparql/blob/master/src/org/datagraph/sparql/Grammar.scala"&gt;Here's a SPARQL parser implementation in Scala&lt;/a&gt;, a language with powerful pattern matching features for good parsing, and it's 500 lines of code.  It compiles to S-expressions, the parsing of which is &lt;a href="http://github.com/datagraph/datagraph-sparql/blob/master/src/org/datagraph/sxp/Grammar.scala"&gt;about 30 lines&lt;/a&gt;.  Hmm.)&lt;/p&gt;

&lt;p&gt;If the protocol had been defined as S-expressions, the distinction would not exist and the syntax could be as expandable as the current functions (the current syntax would just be more functions).  The new 1.1 service discovery mechanism is excellent and extendible and would allow the standard to grow dynamically instead of becoming bogged down in features for particular use cases.  New baseline implementations of SPARQL would be easy to implement and grow incrementally, and the current human-readable format can be implemented in terms of these expressions.&lt;/p&gt;

&lt;p&gt;The web of ontologies has grown with ad-hoc definitions created by people used to fill their needs.  Standards grow organically around the ones that are needed most, others languish.  Why should SPARQL functions have this kind of flexibility, but not the syntax?  The distinction makes implementation overly difficult and is slowing the expansion of the Semantic Web.&lt;/p&gt;

&lt;p&gt;In fact, it turns out that Jena has been &lt;a href="http://jena.hpl.hp.com/wiki/SSE"&gt;parsing to S-expressions&lt;/a&gt; for some time.  If you're an implementor, why would you do it any other way, especially when the standard can change as much as it does in 1.1?  Any implementation will have to come up with something equivalent to S-expressions if you are going to be able to upgrade your engine implementation to meet standards like this when they are finalized.  If people are doing it anyway, why not just make it the standard?&lt;/p&gt;

&lt;p&gt;The SPARQL Working Group should be working on a definition for a function list and discovery protocol for S-expressions, and not for what we currently call SPARQL.  What we call SPARQL is something that should compile to a simpler standard if various vendors want to implement it.  S-expressions allow maximally simple parsing maximally simple serialization, and the ability to do feature discovery on core features of the language, not just portions which are blessed with the ability to be extended.  S-expressions are easier for machines to generate for wide variety of automated use cases, far wider, I would venture, than the set of use cases for the human-readable queries.&lt;/p&gt;

&lt;p&gt;Please, please, please do not doom the world to write the SPARQL equivalent of &lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt; and &lt;a href="http://api.rubyonrails.org/classes/ActiveRecord/Base.html"&gt;ActiveRecord&lt;/a&gt; for the next 20 years!  We can define a standard that machines can use natively.  Now's the time.&lt;/p&gt;

&lt;p&gt;At any rate, that's my beef in a nutshell.  The working group won't come up with a successful standard until it's easy enough to implement it that workable implementations appear in the languages that are defining the web today.  And when people can use those languages to implement that standard without an army of VC-funded engineers.&lt;/p&gt;

&lt;p&gt;The SPARQL 1.1 proposals make the standard better than before, but it's not the standard we need.  &lt;a href="http://www.w3.org/TR/rdf-sparql-query/#sparqlAlgebra"&gt;The SPARQL algebra&lt;/a&gt; is what needed expansion and specification, not the syntax.&lt;/p&gt;

&lt;p&gt;[1]:  The PHP &lt;a href="http://arc.semsol.org/"&gt;ARC project&lt;/a&gt; has an implementation, but it attempts to directly convert SPARQL to an SQL query on particular table layout in MySQL, and is difficult to convert to general use.  Despite SPARQL's complexity, ARC managed to implement this in just 6400 lines of code.  The parser alone is 2000 lines and the engine another 4400.  The serialization/parsing libraries, however, are fine, and were integrated successfully into the Drupal RDF module.  The PHP &lt;a href="http://www.seasr.org/wp-content/plugins/meandre/rdfapi-php/doc/"&gt;RAP project&lt;/a&gt; has also done some good work and is perhaps more wrappable than ARC, but implements only a subset of SPARQL.&lt;/p&gt;
</description>
    <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2009-11-03T02:02:11Z</dc:date>
    <dc:creator>Ben Lavender</dc:creator>
    <dc:subject>Drupal</dc:subject>
    <dc:subject>RDF</dc:subject>
    <dc:subject>Semantic Web</dc:subject>
    <dc:subject>SPARQL</dc:subject>
    <dc:subject>W3C</dc:subject>
    <dc:source rdf:resource="http://bhuga.net/2009/11/w3c-going-wrong-direction-sparql-11"/>
    <cc:license rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/"/>
  </item>
</rdf:RDF>
