RDF.rbを用いたRDFデータの読み込み


本稿は，RDF.rbを用いてRDFデータを読み込む方法について解説します．

## インストール

RDF.rbの基本的な機能のみを使う場合は，rdfというgemをインストールします．

```
gem install rdf
```

必要なアドオンがあれば，別途インストールします．

```
gem install rdf-rdfxml rdf-turtle
```

アドオンについては，個別にインストールする以外にも，RDF.rbといくつかのアドオンをまとめたlinkeddataというgemをインストールする方法もあります．

```
gem install linkeddata
```

linkeddataに含まれる主なgemを以下に挙げます．

* rdf
* rdf-rdfxml（RDF/XMLの読み書き）
* rdf-turtle（Turtleの読み書き）
* rdf-microdata（Microdataの読み込み）
* rdf-rdfa（RDFaの読み書き）
* rdf-n3（N3の読み書き）
* rdf-json（RDF/JSONの読み書き）
* json-ld（JSON-LDの読み書き）
* rdf-trig（TriGの読み書き）
* rdf-trix（TriXの読み書き）
* sparql（SPARQLによるRDFデータ検索）
* sparql-client（SPARQLエンドポイントへの問い合わせ）


## 基本的な使い方

基本的な使い方は以下の記事を参考にしてください．

http://fumi.me/2010/04/22/rdf-rb/

2010年の記事ですが，2014年現在でも使い方は概ね同じです．
RDFデータの読み込みや出力といった基本的な使い方は，上記の記事を参考にすればよいです．

ここから先は，RDFデータの読み込みについて，上記の記事にはあまり書かれていない使い方について紹介します．


## 拡張子とContent-typeによる，RDF読み込み時のフォーマット自動判定

``RDF::Reader#open``や``RDF::Graph#load``，``RDF::Repository#load``でファイルを読み込む場合，ファイルのフォーマットは拡張子とContent-typeにより自動的に判定されます．
例えば，以下のTurtle形式のファイルとRubyスクリプトを用意し実行すると，スクリプト中でRDFのフォーマットを指定していなくともTurtle形式のファイルとして読み込むことができます．
自動判定には，後述するフォーマット情報を利用しています．

```turtle:sample.ttl
<http://example.com/person1> <http://xmlns.com/foaf/0.1/name> "Alice" .
<http://example.com/person1> <http://xmlns.com/foaf/0.1/known> <http://example.com/person2> .
<http://example.com/person1> <http://xmlns.com/foaf/0.1/known> _:Charlie .
<http://example.com/person1> <http://xmlns.com/foaf/0.1/known> <David> .
# Here is a comment line.
<http://example.com/person2> <http://xmlns.com/foaf/0.1/name> "Bob" .
_:Charlie <http://xmlns.com/foaf/0.1/name> "Charlie" .
<David> <http://xmlns.com/foaf/0.1/name> "David" .
```

```sample.rb
require 'rdf'
require 'rdf/turtle'

# Turtleであると指定していないが，正しく読み込める
graph = RDF::Graph.load("sample.ttl")
```

以下の場合はフォーマット自動判定が有効に機能しません．

* RubyのStringクラスのインスタンスで表現されたRDFデータを読み込む場合
	* そもそもファイルではなく，拡張子やContent-typeが無い

* フォーマットと拡張子，Content-typeの関係が，RDF.rbで定義されているものと異なっている場合
	* どんなフォーマットのRDFファイルもapplication/octet-streamとして送信するサーバなどがあったりします

こうした場合は，エラーが発生したり，エラーは発生しないが正しくRDFデータが読み込まれなかったりします．読み込むファイルのフォーマットが事前に判っている場合は，自動判定に頼らず，フォーマットを指定したRDFデータ読み込みを行うのがオススメです．


## RDF::ReaderやRDF::Graphでフォーマットを指定したRDFデータ読み込み

``RDF::Reader``でRDFデータのフォーマットを指定して読み込むには，以下の方法を用います．

* 各フォーマット用の``RDF::Reader``（``RDF::NTriples::Reader``など）を用いる
* ``RDF::Reader.for()``でフォーマットを指定する
* ``RDF::Reader.open``や``RDF::Reader.new``でオプション``format``を指定する


以下にサンプルコードを示します．

```ruby:フォーマットを指定した読み込み
require 'rdf'
require 'rdf/turtle'

file_name = "sample.ttl"

# 各フォーマット用のRDF::Readerを使う
RDF::Turtle::Reader.open(file_name) do |reader|
end

# RDF::Reader.for()を使う
RDF::Reader.for(:turtle).open(file_name) do |reader|
end

# オプションを使う
RDF::Reader.open(file_name, format: :turtle) do |reader|
end
```

``RDF::Graph``でフォーマットを指定した読み込みを行う場合は，以下の方法を用います．

* ``RDF::Graph#from_``を用いる
* ``RDF::Graph#load``でオプション``format``を用いる

以下はそのサンプルコードです．

```ruby:RDFデータをファイルから読み込む場合
require 'rdf'
require 'rdf/turtle'

file_name = "sample.ttl"
graph = RDF::Graph.new

# RDF::Graph#from_を使う
graph.from_turtle(open(file_name, &:read))

# オプションを使う
graph.load(file_name, format: :turtle)
```

``RDF::Graph#from_``は，[mutable.rb](https://github.com/ruby-rdf/rdf/blob/develop/lib/rdf/mixin/mutable.rb)でmethod_missingを用いて実装されており，from_の後に続く文字列を使って``RDF::Reader.for().new``を呼び出しています．``Kernel#methods``では表示されませんし，エディタの補完機能でも呼び出せないかと思います．``RDF::Graph#from_``の引数は，ファイルパスやURLではなく，Stringクラスのインスタンスで表現されたRDFデータです．

``RDF::Repository``でも``RDF::Graph``と同様の読み込み方が可能です．

``RDF::Reader.for()``や``RDF::Graph#from_``でフォーマット指定に用いるシンボルや文字列は，後述するフォーマット情報を利用します．

## 各フォーマットに対応するシンボル，拡張子，Content-typeを調べる

RDF.rbで利用できる各フォーマットと対応するシンボル，拡張子，Content-typeを調べるには，各フォーマットに対応したアドオンを読み込んだのち，``RDF::Format.entries``や``RDF::Format.reader_symbols``，``RDF::Format.file_extensions``，``RDF::Format.content_types``を実行します．

```ruby:RDFのフォーマットとシンボル，拡張子，Content-typeの確認
require 'rdf'

# アドオンを読み込む前
p RDF::Format.entries #=> 空の配列[]が表示される
p RDF::Format.reader_symbols # 空の配列が表示される
p RDF::Format.file_extensions #=> 空のハッシュ{}が表示される
p RDF::Format.content_types #=> 空のハッシュ{}が表示される

# アドオンの読み込み
require 'rdf/rdfxml'
require 'rdf/turtle'

# フォーマット一覧
p RDF::Format.entries
#=> [RDF::RDFXML::Format, RDF::RDFXML::RDFFormat, RDF::Turtle::Format, RDF::Turtle::TTL]

# シンボル一覧（順序はフォーマット一覧と一致）
p RDF::Format.reader_symbols
#=> [:rdfxml, :rdf, :turtle, :ttl]

# ファイル拡張子とフォーマットの対応付け
p RDF::Format.file_extensions
#=> {:rdf=>[RDF::RDFXML::Format], :ttl=>[RDF::Turtle::Format]}

# Content-typeとフォーマットの対応付け
p RDF::Format.content_types
#=> {"application/rdf+xml"=>[RDF::RDFXML::Format, RDF::RDFXML::RDFFormat], "text/turtle"=>[RDF::Turtle::Format, RDF::Turtle::TTL], "text/rdf+turtle"=>[RDF::Turtle::Format], "application/turtle"=>[RDF::Turtle::Format], "application/x-turtle"=>[RDF::Turtle::Format]}
```


## Base URIを指定した読み込み

``RDF::Reader.open``や``RDF::Reader.new``，``RDF::Graph.load``，``RDF::Graph#from_``などでは，引数にオプション``base_uri``を指定することでBase URIを指定した読み込みが可能です．RDFデータに相対パスを用いたURI表現が含まれる場合などは，このオプションを使うとよいでしょう．

```ruby:BaseURIを指定した読み込み
require 'rdf'
require 'rdf/turtle'

file_name = "sample.ttl"

RDF::Reader.open(file_name, format: :turtle, base_uri: 'http://example.com/base/') do |reader|
end

RDF::Graph.load(file_name, format: :turtle, base_uri: 'http://example.com/base/')
```