LoginSignup
0
1

More than 5 years have passed since last update.

RDF.rbと空白ノード

Last updated at Posted at 2015-12-08

RDFデータをRubyで扱うためのライブラリとして,RDF.rbとそのプラグイン群がある.このライブラリで空白ノードを扱う際に注意する点について記載する.

結論

  • RDF.rbで空白ノードを扱う場合,TurtleやRDF/XMLでシリアライズしない方がよい.
    • 同一のノードIDを与えたはずの空白ノードが,別々のノードとして扱われる
    • その際,ノードIDが正しく記述されない
  • N-Triplesでのシリアライズには問題が無いので,一度N-Triplesでファイル出力してから他のツール(Raptorなど)でTurtleやRDF/XMLへ変換するのがよい.
  • ファイル出力をせず,文字列から直接Raptorを使用したシリアライズをしたい場合は,rdf-raptorを用いるとよい
    • rdf-raptorをrdf-turtleやrdf-rdfxmlと同時にrequireした場合,先に読み込んだ方の処理系が優先される

空白ノードの表現

RDF.rbでは,以下のクラスによってRDFグラフのノードやエッジを表現する

  • RDF::URI
    • URIを持つリソースやプロパティは,RDF::URIクラスのインスタンスとして表現する
  • RDF::Node
    • URIを持たないリソースは,RDF::Nodeクラスのインスタンスとして表現する
  • RDF::Literal
    • リテラルは,RDF::Literalクラスのインスタンスとして表現する

空白ノードは,上記のうちRDF::Nodeクラスのインスタンスとして表現する.Rubyのコードで記述すると以下のようになる.

require 'rdf'

# ノードIDが未定の場合
blank_node = RDF::Node.new

# ノードIDが決まっている場合(例: ノードID=1234)
blank_node = RDF::Node.new('1234')

ノードIDを指定して空白ノードを作成すると,_:1234のようなノードが作成される.ノードIDを指定しない場合,_:g70161525762180のようなノードが作成される.

空白ノードをRDF::Statementの主語や目的語にした場合は,以下のように出力される.

#<RDF::Statement:0x3ff686826614(<http://example.com/resource/1> <http://purl.org/dc/elements/1.1/creator> _:1234 .)>

空白ノードが_:1234となっているのが確認できる.

グラフ中の空白ノード

RDF.rbでは,RDF::Graphクラスのインスタンスとして空のRDFグラフを作成できる.空のグラフに空白ノードを含むRDFトリプルを追加するコードは以下のようになる.

require 'rdf'
require 'rdf/vocab'

# 空のグラフの作成
graph = RDF::Graph.new

# 空白ノードを含むトリプルの作成
statement1 = [
  RDF::URI.new('http://example.com/resource/1'),
  RDF::Vocab::DC11.creator,
  RDF::Node.new('1234'),
]
statement2 = [
  RDF::Node.new('1234'),
  RDF::Vocab::FOAF.name,
  RDF::Literal.new('名無しさん'),
]

# トリプルをグラフに追加
graph << statement1
graph << statement2

# グラフの中身の確認
graph.each_statement do |statement|
  p statement
end

コードの実行結果は以下のようになる.

#<RDF::Statement:0x3fd53504c384(<http://example.com/resource/1> <http://purl.org/dc/elements/1.1/creator> _:1234 .)>
#<RDF::Statement:0x3fd535045c50(_:1234 <http://xmlns.com/foaf/0.1/name> "名無しさん" .)>

この出力結果から,_:1234という空白ノードを含む2つのトリプルがグラフに格納されていることがわかる.

シリアライズ後の空白ノード

RDF.rbでは,RDF/XMLやTurtleに対応するためのプラグインとして以下の2種類が挙げられる

  • Pure Rubyなプラグイン
    • rdf-turtle,rdf-rdfxmlなど
  • Raptor (C言語で記述された外部ライブラリ) を用いるプラグイン
    • rdf-raptor

rdf-turtleとrdf-rdfxmlを使用した場合

空白ノードを含むRDFグラフをN-Triples,Turtle,RDF/XMLで出力するコードが以下である.

require 'rdf'
require 'rdf/vocab'
require 'rdf/turtle'
require 'rdf/rdfxml'

graph = RDF::Graph.new
statement1 = [
  RDF::URI.new('http://example.com/resource/1'),
  RDF::Vocab::DC11.creator,
  RDF::Node.new('1234'),
]
statement2 = [
  RDF::Node.new('1234'),
  RDF::Vocab::FOAF.name,
  RDF::Literal.new('名無しさん'),
]
graph << statement1
graph << statement2

puts "\n\n==== N-Triples ====\n\n"
puts graph.dump(:ntriples)

puts "\n\n==== Turtle ====\n\n"
puts graph.dump(:turtle)

puts "\n\n==== RDF/XML ====\n\n"
puts graph.dump(:rdfxml)

このコードを実行すると,以下のように表示される.

==== N-Triples ====

<http://example.com/resource/1> <http://purl.org/dc/elements/1.1/creator> _:1234 .
_:1234 <http://xmlns.com/foaf/0.1/name> "名無しさん" .


==== Turtle ====


<http://example.com/resource/1> <http://purl.org/dc/elements/1.1/creator> [] .

 [ <http://xmlns.com/foaf/0.1/name> "名無しさん"] .


==== RDF/XML ====

<?xml version='1.0' encoding='utf-8' ?>
<rdf:RDF xmlns:ns0='http://purl.org/dc/elements/1.1/' xmlns:ns1='http://xmlns.com/foaf/0.1/' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
  <rdf:Description rdf:about='http://example.com/resource/1'>
    <ns0:creator rdf:nodeID='1234' />
  </rdf:Description>
  <rdf:Description>
    <ns1:name>名無しさん</ns1:name>
  </rdf:Description>
</rdf:RDF>

N-Triplesは_:1234という空白ノードが正しく出力されているが,Turtleでは1つ目のトリプルの目的語と2つ目のトリプルの主語が別々の空白ノードとして扱われている.RDF/XMLも同様で,1つ目のトリプルの目的語はrdf:nodeID='1234'として正しく出力されているが,2つ目のトリプルにノードIDが与えられていない.

rdf-raptorを使用した場合

空白ノードを含むRDFグラフをN-Triples,Turtle,RDF/XMLで出力するコードが以下である.

require 'rdf'
require 'rdf/vocab'
require 'rdf/raptor'

graph = RDF::Graph.new
statement1 = [
  RDF::URI.new('http://example.com/resource/1'),
  RDF::Vocab::DC11.creator,
  RDF::Node.new('1234'),
]
statement2 = [
  RDF::Node.new('1234'),
  RDF::Vocab::FOAF.name,
  RDF::Literal.new('名無しさん'),
]
graph << statement1
graph << statement2

puts "\n\n==== N-Triples ====\n\n"
puts graph.dump(:ntriples)

puts "\n\n==== Turtle ====\n\n"
puts graph.dump(:turtle)

puts "\n\n==== RDF/XML ====\n\n"
puts graph.dump(:rdfxml)

require以外は,rdf-turtleやrdf-rdfxmlを使用した場合と全く同じである.ちなみに,rdf-turtleやrdf-rdfxmlをrdf-raptorと一緒にrequireした場合は,先に読み込まれた方がシリアライズに使用される.

このコードを実行すると,以下のように表示される.
なお,事前にraptorのバージョン2.0.15をインストールしている.

==== N-Triples ====

<http://example.com/resource/1> <http://purl.org/dc/elements/1.1/creator> _:1234 .
_:1234 <http://xmlns.com/foaf/0.1/name> "\u540D\u7121\u3057\u3055\u3093" .


==== Turtle ====

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

<http://example.com/resource/1>
    <http://purl.org/dc/elements/1.1/creator> [
        <http://xmlns.com/foaf/0.1/name> "名無しさん"
    ] .



==== RDF/XML ====

<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <rdf:Description rdf:about="http://example.com/resource/1">
    <ns0:creator xmlns:ns0="http://purl.org/dc/elements/1.1/" rdf:nodeID="1234"/>
  </rdf:Description>
  <rdf:Description rdf:nodeID="1234">
    <ns0:name xmlns:ns0="http://xmlns.com/foaf/0.1/">名無しさん</ns0:name>
  </rdf:Description>
</rdf:RDF>

rdf-turtleやrdf-rdfxmlを使用した場合とは異なり,同一の空白ノードが正しく処理されていることがわかる.

以上から,RDF.rbで空白ノードを含むTurtleファイルやRDF/XMLファイルを出力したい場合,Raptorをインストールできる環境ならばrdf-raptorを使うとよい.Raptorをインストールできないなら,一度N-Triplesで出力してから他のツールでTurtleやRDF/XMLに変換するのがよい.

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1