セマンティック Web、Linked Data、そして Drupal: 第 1 回 RDF を使ってデータを公開する

Drupal 7 は主流のコンテンツ管理システムとしては初めて、セマンティック Web 技術をそのコアでサポートします。セマンティック Web 技術は使用するのが簡単で、Web を文書の Web からデータの Web へと引き上げることができます。この記事では、Web データの相互運用性を改善してデータ共有を効率化する方法を説明し、RDF でコンテンツを公開することによって、Drupal 7 を使用して Linked Data を公開する例を紹介します。

Lin Clark, Drupal Developer, Digital Enterprise Research Institute, NUI Galway

Author photoLin Clark は、Linked Data を専門とする Drupal 開発者です。Drupal 7 コア・イニシアチブでは RDF に貢献し、2010 Google Summer of Code の一部として SPARQL Views を作成しました。また。Linked Data 技術を日常的アプリケーションで使用するメリットについて広範囲にわたって話しています。カーネギー・メロン大学で教育を受けた彼女は、現在はアイルランド国立大学ゴールウェイ校のDigital Enterprise Research Institute でリサーチ修士号を目指しています。詳細については、lin-clark.com にアクセスしてください。



2011年 4月 12日

はじめに

2001年、今では伝説となっている記事、「The Semantic Web」のなかで Tim Berners-Lee 氏が語った世界は、携帯型エージェントを使って他のエージェントとデータを交換することで、携帯型エージェントのみを使って決定を下すなど、物事をシンプルに行えるようになるという世界です。それ以来、セマンティック Web の取り組みは大きな前進を遂げ、ここ数年は一層実際的な方向に進んでいます。Linked Data イニシアチブでは、Berners-Lee 氏が彼の構想を実現する上で最も重要な鍵と称している、データ相互運用性を研究開発の焦点としてきました。

Linked Data 技術のメリットは、大量のカスタム・コードを作成しなくても得ることができます。この記事では、Drupal 7 が広範囲に及ぶデータ相互運用性を実現する仕組みを探り、RDF (Resource Description Framework) を使用して Web データを公開する方法を学びます。記事で使用するソース・コードはダウンロードすることができます。

前提条件

この記事で説明する例に従うには、Drupal 7 サイトをインストールしてください。Drupal を実行するには、PHP とデータベース・サーバー (MySQL など) が必要です。


データの相互運用性

現在、Web 上の情報の多くには相互運用性がありません。例えば、あるサイトからデータを取得して、それを別のサイトからのデータとマッシュアップするとしたら、ページから必要な情報だけを取り出すカスタム・クローラーを作成しなければなりません。これは特に、個人や政府、教育機関によって実行されているサイトなど、予算の限られたサイト上の情報を使う場合に当てはまります。開発者がサイト上の構造化された情報にアクセスできるとしても、大抵は、サイトによって異なる独自仕様の API を使うことになります。

Linked Data イニシアチブは、ごく一部のセマンティック Web 技術と概念 (RDF など) を使用して、相互運用性の問題を解決し、Web 上のデータをより簡単に再利用して統合できるようにする取り組みです。

データの相互運用性に新たな焦点が置かれ、企業がセマンティック Web 技術の威力を理解するようになるとともに、開発および技術革新のペースが加速しています。例えば、Google は RDF を属性で使うことによって (RDFa)、リッチ・スニペットを可能にしています。リッチ・スニペットは、Google のアルゴリズムを適用して、Web ページに埋め込まれた構造化データを強調表示するスニペットの表示形式です。図 1 に示すように、リッチ・スニペットでページ・コンテンツの特定の部分が目立つように表示することで、より参考になる検索結果にすることができます。この拡張された検索結果により、さまざまなアカウントでクリックスルー・レートが 15%から 30%増加したことが示されています。

図 1. レシピの場合の Google リッチ・スニペット
Google リッチ・スニペットはページの特定の要素を目立たせて表示します

Facebook では、2010年からサイトの作成者が自分のサイトに配置できる「いいね!」ボタンの駆動に RDFa を使用しています。ほんの少しの RDFa を Web ページに組み込むだけで、Facebook のページと同等の機能を持つページになり、サイトの訪問者が「いいね!」ボタンをクリックすると、その訪問者と外部ページが Facebook で接続されます。このような相互運用性の威力は、いくつかの単純な原則に従うとともに、ほんのわずかなセマンティック Web 技術を適用することによってもたらされます。


RDF、語彙、そして Linked Data の原則

Linked Data で最も重要な原則となるのは、Web 上の情報にはシリアル ID やその他の ID を使用する代わりに、それぞれに別個の名前を使用することです。別個の名前は、ドメイン・ネーミング・システムを使うと簡単に作成することができます。例えば、Jane Doe という名前の女性に関する情報を Web サイトで提供している場合、この情報と Jane Doe という名前の別の女性に関する情報とを区別するのは非常に困難です。そこで、http://example.com/people/jane-doe という ID を使用すれば、対象とする Jane Doe を簡単に識別できるようになります。このような形式の ID は、HTTP URI と呼ばれます。

HTTP URI を使用して情報を識別するということは、Web のアーキテクチャーを使用して、Jane Doe に関する詳細情報を提供できるということでもあります。例えば、ユーザーが http://example.com/people/jane-doe にアクセスすると、Jane Doe の名前、オンライン・アカウント、拠点とする場所、著書などの情報が表示されるようにすることができます。

RDF と語彙を使用してデータを公開する

これまでにデータベースやオブジェクト指向言語を扱った経験があれば、RDF には親しみが持てるはずです。表 1 に示すように、RDF は単なるエンティティー属性値 (entity-attribute-value) モデルに過ぎません (ただし RDF では大抵の場合、属性はプロパティーと呼ばれます)。

表 1. エンティティー属性値モデル
エンティティープロパティー
http://example.com/people/jane-doenameJane Doe

相互運用性を確実にするには、誰でも理解できるプロパティー名を使用しなければなりません。したがって、プロパティーにも URI を使用する必要があります。プロパティー URI のバンドルは、語彙 (正式に言うと、オントロジー) と呼ばれる形で公開されています。

以下は、語彙の例です。

FOAF (Friend of a Friend)
人に関する情報を記述するためのプロパティーを提供します。例: namehomepagembox (E メール)、accountbased_near
DC (Dublin Core)
出版物を記述するためのプロパティーを提供します。例: abstractcreateddateCopyrightedpublisher
SIOC (Semantically-Interlinked Online Communities)
オンライン・ソーシャル・ネットワークとそのユーザーを記述するためのプロパティーを提供します。例: followshas_replylast_reply_datemoderator_of、subscriber_of

語彙についての詳細は、「参考文献」を参照してください。

URI をプロパティーとして使用して、前述の例のエンティティー属性値 (entity-attribute-value) のステートメントを作成すると、以下のようになります。

<http://example.com/people/jane-doe> <http://xmlns.com/foaf/0.1/name> "Jane Doe"

URI 値は先頭から終わりまでまとめて不等号括弧で囲み、リテラル値は引用符で囲みます。

上記のようなステートメントをもう少し読みやすくするには、簡易 URI (CURIE) を使用し、CURIE の接頭辞の意味を定義するという方法があります。リスト 1 はその一例です。

リスト 1. CURIE を使用した RDF ステートメント
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX person: <http://example.com/people/>

person:jane-doe foaf:name "Jane Doe"

このようにすると、Web アーキテクチャーがある種のデータベース構造になります。ただし、すべてのデータが 1 つのデータストアにあるわけではなく、あちこちの独立したサイトに存在する可能性がありますが、それらのデータでも必要に応じて簡単に収集して統合することができます。

このような RDF データ・セットからデータを取得するには、SPARQL 問い合わせ言語を使用することができます。


SPARQL を使用して DBpedia にクエリーを実行する

データ・セットや情報ハブのなかには、Linked Data によって公開されているものが多くあります。ウィキペディアも、その 1 つです。ウィキペディアのコンテンツの大部分は自由形式のテキストであり、Linked Data として公開するのは難しいものの、ウィキペディアのページの多くには右側に情報ボックスがあり、ここに豊富な構造化情報が記載されています。例えば、都市の人口や著者の専門分野とペンネームなどといった情報です。

DBpedia は、コミュニティーによる取り組みとして、ウィキペディアから構造化データを抽出し、その情報を RDF で公開して Web 上で利用できるようにすることを目的としたものです。この RDF ファイルは、アプリケーションで使用できるようにファイル全体をダンプとしてダウンロードすることができます。DBpedia にはデモ用のクエリー・インターフェースも用意されています。

DBpedia のデータを探索するには、まず、トピックに関連付けられた DBpedia URI を見つけておくと簡単です。例えば、ピッツバーグの人口やその他の情報を調べたい場合、最初にウィキペディアの該当するページの URL を見つけて、次にリスト 2 の SPARQL クエリーを使って、そのページに関連付けられた DBpedia URI を検索します。この例の接頭辞は Snorql インターフェースに組み込まれているため、接頭辞を宣言せずに CURIE を使用することができます。

リスト 2. ピッツバーグの DBpedia URI を検索するクエリー
SELECT ?uri WHERE {
  ?uri foaf:page <http://en.wikipedia.org/wiki/Pittsburgh>
}

探していた URI は、 <http://dbpedia.org/resource/Pittsburgh> です (ただし、リスト 3 に示すように、Snorql インターフェースは単に別のクエリーへのリンクを示すだけです)。

リスト 3. DBpedia でピッツバーグに関するすべての情報を検索する場合のクエリー
SELECT ?property ?hasValue ?isValueOf
WHERE {
  { <http://dbpedia.org/resource/Pittsburgh> ?property ?hasValue }
  UNION
  { ?isValueOf ?property <http://dbpedia.org/resource/Pittsburgh> }
}

上記のクエリーを理解しきれないとしても、心配しないでください。理解しておかなければならない重要な点は、このクエリーを実行すると、ピッツバーグの年間平均気温、緯度と経度の座標、市旗の画像、この都市で生まれた有名人など、DBpedia に含まれるピッツバーグに関するすべての情報が表示されることです。

DBpedia から引き出したい情報が、例えばピッツバーグの都市部の人口だけであるとしたら、リスト 4 に記載するようなクエリーを使用することができます。

リスト 4. ピッツバーグの人口を検索する場合のクエリー
SELECT ?population WHERE {
<http://dbpedia.org/resource/Pittsburgh> dbpedia2:populationMetro ?population
}

さまざまな情報を結ぶリンクをトラバースすることで、さらに多くの事実を突き止めることもできます。詳細を探るには、ピッツバーグで生まれた人のリストを取得してください。dbpedia:ontology/birthPlace の代わりに dbo:birthPlace と省略できるように、リスト 5 では dbo 接頭辞が追加されています。

リスト 5. ピッツバーグ生まれの人のリストを取得する場合のクエリー
PREFIX dbo: <http://dbpedia.org/ontology/>

SELECT ?person WHERE {
?person dbo:birthPlace <http://dbpedia.org/resource/Pittsburgh> .
}

これで、ピッツバーグ生まれの人のリストを取得することができました。さらに興味深いものにするために、今度はこのリストを、特定の条件を基準にフィルタリングします。例えば、アメリカ人のブロガーとして分類されている人々にリストを絞り込むとしたら、rdf:type という特殊なプロパティーを使用します (リスト 6 を参照)。

リスト 6. ピッツバーグ生まれのアメリカ人ブロガーを検索する場合のクエリー
PREFIX dbo: <http://dbpedia.org/ontology/>

SELECT ?person WHERE {
?person dbo:birthPlace <http://dbpedia.org/resource/Pittsburgh> ;
        rdf:type <http://dbpedia.org/class/yago/AmericanBloggers> .
}

ピッツバーグ生まれのブロガーのリストに関して、さらに詳しい情報を取得することができます。リスト 7 に、略歴として使える要約を取得する方法を示します。

リスト 7. ピッツバーグ生まれのアメリカ人ブロガーの要約を取得する場合のクエリー
PREFIX dbo: <http://dbpedia.org/ontology/>

SELECT ?person ?bio WHERE {
?person dbo:birthPlace <http://dbpedia.org/resource/Pittsburgh> ;
        rdf:type <http://dbpedia.org/class/yago/AmericanBloggers> ;
        dbo:abstract ?bio .
}

お気付きかもしれませんが、このクエリーは予想した以外の情報も返してきます。それは、英語での要約に加えて、翻訳されているすべての言語での要約です。英語版の要約だけを取得するには、FILTER を使用して、言語の値をチェックします (リスト 8 を参照)。

リスト 8. 英語の要約を取得する場合のクエリー
PREFIX dbo: <http://dbpedia.org/ontology/>

SELECT ?person ?bio WHERE {
?person dbo:birthPlace <http://dbpedia.org/resource/Pittsburgh> ;
        rdf:type <http://dbpedia.org/class/yago/AmericanBloggers> ;
        dbo:abstract ?bio .
FILTER langMatches( lang(?bio), "en" )
}

上記のクエリーは、英語版の要約だけを返します。

このように、SPARQL では必要な情報を簡単に RDF データ・セットから取得できるため、Web 上のデータに簡単にアクセスして再利用できるようになります。


Drupal 7 での RDF サポート

Drupal は小規模なデータを公開するサイトに対し、広範囲に及ぶデータ相互運用性を実現する機能を提供します。Drupal は、開発者およびエンド・ユーザーが容易に堅牢なデータ入力フォームを作成できるようにするオープンソースのコンテンツ管理システムです。Drupal で作成するフォームは、構造化データを取り込んで、そのデータをさまざまな方法で柔軟にフォーマット設定するには最適です。

Drupal 7 を使用すれば、小規模なサイトでも、RDF を使ってデータを公開することができます。サイト上のページや記事の基本的なコンテンツは、新規の Drupal 7 サイトで公開されるようにデフォルトで設定されています。このオファリングの鍵となっているのは、RDF Mapping APIです。この API では、あらゆるフォームのフィールドを RDF プロパティーにマッピングし、あらゆるコンテンツ・タイプを RDF タイプにマッピングすることができます。例えば、サイトにレコーディング・アーティストのリストがある場合、そのコンテンツのタイプは mo:MusicArtist タイプにして、フィールドは mo:fanpagemo:discographymo:biography などにマッピングできるといった具合です。

マッピングが定義されているコンテンツ・タイプは、いずれも RDFa (HTML 属性での RDF) を使用して自動的にコンテンツを公開します。前に使用した Jane Doe のシナリオを引用すると、RDFa ではリスト 9 に記載するステートメントになります。

リスト 9. RDFa で表現されたリスト 1 のステートメント
<div about="http://example.com/people/jane-doe">
  <h1 property="foaf:name">Jane Doe</h1>
</div>

マークアップのフォーマット設定は Drupal が処理するため、有効な RDFa をいとも簡単に公開することができます。このように、Drupal によって、サイトの所有者は他のサイトとデータを共有できるだけでなく、Google のリッチ・スニペットのような、とっておきの機能も簡単に利用できるようになります。


Drupal でのカスタム RDF マッピングのセットアップ

このセクションでは、Linked Data を公開する作業に取り掛かります。この例では、料理のレシピを公開して Google リッチ・スニペットとして表示できるように、Recipe コンテンツ・タイプを作成します。

準備手順

記事で使われているソース・コードは、ここからダウンロードすることができます。

この例に従うには、Drupal 7 サイトをインストールしてください。Drupal を実行するには、PHP と データベース・サーバー (MySQL など) が必要です。PHP とデータベース・サーバーが開発環境にすでにインストールされている場合には、インストール・ガイドの手順に進んでください。まだインストールされていなければ、Acquia では簡単に使える Acquia Stack Installer を用意しているので、これを使用して Apache Web Server、PHP、MySQL サーバー、および Drupal 7 サイトをインストールします。詳細については、「参考文献」を参照してください。

サイトの準備が完了したら、2 番目のツールバーにある「Add content (コンテンツの追加)」ボタンを使用して、「Article (記事)」を追加してみてください。新しいコンテンツは、フロント・ページのリストに表示されます。ソース・コードを調べると、HTML に RDFa が組み込まれていることがわかります。「Page (ページ)」コンテンツ・タイプと「Article (記事)」コンテンツ・タイプには両方ともデフォルトの RDF マッピングがあるため、例えば記事の著者は、sioc:has_creator でマークアップされます。

このセクションの残りでは、新しいコンテンツ・タイプを作成し、このコンテンツ・タイプに固有のカスタム・マッピングをコードで定義します (コンテンツ・タイプとそのマッピングは、コードの代わりにユーザー・インターフェースを使って定義することもできますが、それについてはこの記事では説明しません)。

モジュールを作成する

Drupal モジュールにまず必要なのは、.info ファイルです (リスト 10 を参照)。このファイルは、モジュールに含まれるファイルに関する情報、そしてモジュールが依存する他のモジュールに関する情報をシステムに提供します。

リスト 10. rdf_example.info ファイル
name = RDF Example
description = Demonstrates an RDF mapping using the RDF Mapping API.
core = 7.x
dependencies[] = richsnippets 
dependencies[] = field_collection

依存関係の配列は Drupal に対し、このモジュールをインストールする前にインストールしておかなければならない他のモジュールを指示します。field_collection 自体も Entity API に依存することに注意してください。これらのモジュールをダウンロードするには、「参考文献」でそれぞれのリンクを参照してください。

RDFa には Google に合わせたマイナーな調整が必要なので、この例ではリッチ・スニペット・モジュールへの依存関係を追加します。この依存関係は、field_collection に追加します。それは、このモジュールを使用して、栄養成分の情報や材料などのフィールドのグループを作成するためです。

コンテンツ・タイプを作成する

次のステップは、.install ファイル内でコンテンツ・タイプを作成し、該当するフィールドを関連付けることです。.install ファイルは、以下に説明する 3 つの関数で構成されています。

関数目的
rdf_example_installhook_install を実行するこの関数は、Drupal モジュールがインストールされるときに呼び出されます。
_rdf_example_installed_fieldsrdf_example_install によって呼び出される private 関数です。この関数によって、必要なフィールド定義が提供されます。
_rdf_example_installed_instances同じく rdf_example_install によって呼び出される private 関数です。この関数は、コンテンツ・タイプに関連付けるフィールドを定義します。

rdf_example_install 内に、まずは Recipe ノード・タイプを作成します (リスト 11 を参照)。

リスト 11. rdf_example_install にノード・タイプを定義する
  // Define the node type.
  $rdf_example = array(
    'type' => 'recipe',
    'name' => $t('Recipe'),
    'base' => 'node_content',
    'description' => $t('The recipe node is defined to demonstrate RDF mapping.'),
  );

  // Set additional defaults and save the content type.
  $content_type = node_type_set_defaults($rdf_example);
  node_type_save($content_type);

Recipe ノード・タイプに関連付けることが可能なフィールドを作成します (リスト 12 を参照)。これらのフィールドは、他のモジュールが再利用したり、ユーザーが Fields UI から再利用したりすることもできます。フィールド定義は、コードを簡潔に維持するために、別の関数 (_rdf_example_installed_fields) に保管します。

リスト 12. ノード・タイプに追加可能なフィールドを作成する
  foreach (_rdf_example_installed_fields() as $field) {
    field_create_field($field);
  }

上記のコードは _rdf_example_installed_fields を呼び出して、インストールしなければならないフィールドのリストを取得します。フィールド定義には、フィールドの名前と型、そしてカーディナリティー (フィールドが持つことのできる値の数) が含まれます。フィールドのなかには、追加の設定が構成されるものもあります。フィールド定義については、この例では使用されるフィールドだけを作成します。フィールドをどのコンテンツ・タイプに関連付けるかを心配する必要はありません。

リスト 13 では、recipe_nutrition が特殊なタイプの field_collection フィールドとなっている点に注目してください。このフィールドがリンクしている field_collection エンティティーは、固有の RDF タイプを持ち、固有のフィールドを含めることができます。このエンティティー・タイプは、recipe_nutrition に対して自動的に作成されます。このエンティティーには、リスト 14 に示す次のステップでフィールドを関連付けます。

リスト 13. _rdf_example_installed_fields() にフィールドを定義する
array(
    'recipe_photo' => array(
      'field_name' => 'recipe_photo',
      'cardinality' => 1,
      'type'        => 'image',
    ),
    'recipe_summary' => array(
      'field_name'  => 'recipe_summary',
      'cardinality' => 1,
      'type'        => 'text',
      'settings'    => array(
        'max_length' => 500,
      ),
    ),
    'recipe_nutrition' => array(
      'field_name'  => 'recipe_nutrition',
      'cardinality' => 1,
      'type'        => 'field_collection',
    ),
    'recipe_serving_size' => array(
      'field_name'  => 'recipe_serving_size',
      'cardinality' => 1,
      'type'        => 'text',
    ),
    'recipe_calories' => array(
      'field_name'  => 'recipe_calories',
      'cardinality' => 1,
      'type'        => 'number_integer',
    ),
  );

これで、システムにフィールドが作成されたので、次は field_create_instance を使って、フィールドのインスタンスを Recipe コンテンツ・タイプと Recipe Nutrition フィールド・コレクションに関連付けます (Drupal では、これらのタイプはバンドルと呼ばれます)。この場合も同じく、インスタンス定義は別の関数 (_rdf_example_installed_instances) に保管して、コードを簡潔に維持します。リスト 14 に一例を記載します。

リスト 14. rdf_example_install でフィールドのインスタンスをコンテンツ・タイプに関連付ける
  foreach (_rdf_example_installed_instances() as $bundle_name => $bundle) {
    foreach ($bundle as $instance) {
      $instance['entity_type'] = $bundle_name == 'recipe' ? 'node' : 
'field_collection_item';
      $instance['bundle'] = $bundle_name;
      field_create_instance($instance);
    }
  }

上記のコードは _rdf_example_installed_instances を呼び出して、フィールドのインスタンス定義を取得します。_rdf_example_installed_instances では配列を作成し、その配列に、このインスタンスを関連付けるタイプでキーを付けます。この例でそのタイプに該当するのは、Recipe コンテンツ・タイプまたは Recipe Nutrition フィールド・コレクションのいずれかです (リスト 15 を参照)。

リスト 15. _rdf_example_installed_instances() でインスタンスを定義する
  $instances = array();
  $instances['recipe'] = array(
    'recipe_photo' => array(
      'field_name'  => 'recipe_photo',
      'label'       => $t('Photo of the prepared dish'),
    ),
    'recipe_summary' => array(
      'field_name' => 'recipe_summary',
      'label'       => $t('Short summary describing the dish'),
      'widget'      => array(
        'type'    => 'text_textarea',
      ),
    ),
    'recipe_nutrition' => array(
      'field_name' => 'recipe_nutrition',
      'label'      => $t('Recipe Nutrition Information'),
    ),
  );
  $instances['recipe_nutrition'] = array(
    'recipe_serving_size' => array(
      'field_name' => 'recipe_serving_size',
      'label'       => $t('Serving size'),
    ),
    'recipe_calories' => array(
      'field_name' => 'recipe_calories',
      'label'       => $t('Calories'),
    )
  );

コンテンツを RDF にマッピングする

定義したフィールドとコンテンツ・タイプの RDF マッピングは、.module ファイル内で作成します。このモジュールにはコンテンツ・タイプが定義されているため、そのコンテンツ・タイプの RDF マッピングを、 hook_rdf_mapping を使用して作成します。ここでは、別のモジュールによって作成されたコンテンツ・タイプのマッピングを変更する方法は記載しませんが、既存のマッピングを変更するには、install 関数で、RDF Mapping API が提供する rdf_mapping_load 関数と rdf_mapping_save 関数を使用することになります。

インスタンスを作成したときと同じように、この配列はバンドル・タイプで作成します。リスト 16 に Recipe コンテンツ・タイプのマッピングの定義を、そしてリスト 17 に Recipe Nutrition フィールド・コレクションのマッピングの定義を記載します。

リスト 16. rdf_example.module から抜粋したレシピの RDF マッピング定義
    'recipe' => array(
      'type' => 'node',
      'bundle' => 'recipe',
      'mapping' => array(
        'rdftype' => array('v:Recipe'),
        // We don't use the default bundle mapping for title. Instead, we add
        // the v:name property. We still want to use dc:title as well, though,
        // so we include it in the array.
        'title' => array(
          'predicates' => array('dc:title', 'v:name'),
        ),
        'recipe_summary' => array(
          'predicates' => array('v:summary'),
        ),
        // The photo URI isn't a string but instead points to a resource, so we
        // indicate that the attribute type is rel. If type isn't specified, it
        // defaults to property, which is used for string values.
        'recipe_photo' => array(
          'predicates' => array('v:photo'),
          'type' => 'rel',
        ),
        'recipe_nutrition' => array(
          'predicates' => array('v:nutrition'),
          'type' => 'rel',
        ),
      ),
    ),
リスト 17. rdf_example.module から抜粋したレシピの栄養成分の RDF マッピング定義
    'nutrition' => array(
      'type' => 'field_collection_item',
      'bundle' => 'recipe_nutrition',
      'mapping' => array(
        'rdftype' => array('v:Nutrition'),
        'recipe_serving_size' => array(
          'predicates' => array('v:servingSize'),
        ),
        'recipe_calories' => array(
          'predicates' => array('v:calories'),
        ),
      ),
    ),

最後に、hook_rdf_namespaces を実装して、接頭辞の定義が HTML 文書の先頭に組み込まれるようにします (リスト 18 を参照)。

リスト 18. rdf_example.module から抜粋した RDF 名前空間の定義
function rdf_example_rdf_namespaces() {
  return array(
    // Google's namespace for their custom vocabularies.
    'v' => 'http://rdf.data-vocabulary.org/#', 
  );
}

リッチ・スニペットのテスト

完成したモジュールをインストールしてみてください。Recipe コンテンツ・タイプが「Add content (コンテンツを追加)」ページに表示されるはずです。

タイトル、画像、要約の各フィールドは、Recipe ノード・フォームで使用可能になります。リッチ・スニペットをテスト・ツールで表示するには、画像を追加する必要があります。ノードを送信すると、栄養成分の情報を追加するオプションが表示されるので、少なくともカロリー量を追加してください。

レシピを用意した後は、リッチ・スニペットのテスト・ツールでテストしてください。プレビューに、画像とカロリー量が表示されるはずです。


まとめ

Linked Data 技術は、Web のデータの相互運用性と再利用性を高め、データを扱いやすくするのに役立ちます。Google や Facebook のような企業は、データを共有しやすくするために、すでに Linked Data 技術をベースにするようになっています。Drupal を使用することで、大量のカスタム・コードを作成しなくても、小規模なデータを公開するサイトとそのコンシューマーはLinked Data 技術がもたらすメリットを得られます。RDF を使用してサイトのデータを公開する方法は、この記事で説明したとおりです。

この連載の第 2 回では、他から提供されているデータを使用する方法、そしてそのデータと自分のデータを Drupal Web サイトで統合する方法を説明します。お楽しみに。


ダウンロード

内容ファイル名サイズ
Article source coderdf_example.zip3KB

参考文献

学ぶために

製品や技術を入手するために

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=659388
ArticleTitle=セマンティック Web、Linked Data、そして Drupal: 第 1 回 RDF を使ってデータを公開する
publish-date=04122011