1. 一般的な質問
とっかかりはどこがいいですか?
Mozilla では RDF には 2つの主要な目的のために利用します。 第一の目的は単純なもので、小さいデータを保存するクロスプラットフォームなデータベースとしてです。 第二の目的はより重要なもので、情報を表示する抽象"API"として XULテンプレート と共に使用されます。 [RDF_in_Fifty_Words_or_Less RDFを50単語以下で説明しなさい] は RDF が Mozilla で何を行うのかについてのてっとりばやい説明になっています。 バックエンドアーキテクチャ の文書は Mozilla の RDF 実装がどのように動くのかについてより詳細な説明をしています。 またこの文書から、他に利用する際のインターフェースについて手早い概要が得られます。
Open Directory("dmoz") のどこから情報得られますか?
残念、ここじゃないですね! http://www.dmoz.org/ から始めましょう。 dmoz の日本語の Mozilla ディレクトリは こちら
データソースって何ですか?
RDF の切り口は一般に 2通りあります: ノードと弧<arc>のグラフとして、または論理学の命題 <logical statement> の「スープ」としての視点です。 データソースはある理由により集められたサブグラフ(もしくは命題の集合、これらは視点により違う) 今あるデータソースの例としては、「ブラウザのブックマーク」、「ブラウザ全体の履歴」、「IMAP メイルアカウント」、「NNTPニュースサーバー」、「RDF/XML ファイル」といったものがあります。 Mozilla はデータソースを composite data source を用いて組み合わせることができます。 これは積み重ねられたグラフや、命題群の集合(小さな定理の集まり)を融合させることに似ています。 同じ RDFリソースに関する命題群を混ぜ合わせることができます: 例えば、あるウェブサイトの「最終訪問日」は「ブラウザ全体の履歴」データソースから得られます。さらに、そのウェブサイトへ行くために打ち込む「ショートカットキーワード」は「ブラウザブックマーク」から得られます。どちらのデータソースも「ウェブサイト」を URL で参照します: これがデータソースを効果的に「混ぜ合わ」せるための「鍵」となります。 データソースの書き方についてより詳しい説明は、 [datasource-howto.html Datasource HOWTO] を参照してください。
Mozilla はデータソースをどう管理していますか?
RDFサービス はロードした全てのデータソースのテーブルを管理します。 このテーブルはデータソースの "URI" によって索引付けられます。 データソースの URI とは、 RDF/XML ファイルの URL か rdf:
で始まる組み込みデータソースを参照する特殊な URI です。 GetDataSource()
メソッドを用いて RDFサービスを介してデータソースをロードできます。 URI引数が RDF/XML ファイルの URL を指していたら、RDFサービスはRDF/XMLデータソースを作成し、それを非同期的にパースします。 データソースはそれへの最後の参照が解放されるまで「キャッシュ」されます。 URI引数が組み込みデータソースを参照していた場合、RDFサービスは XPCOM のComponent Manager を用いて、「特殊」URI と @mozilla.org/rdf/datasource;1?name=
. というプリフィクスから構成されるContractIDを持つコンポーネントをロードします。 例として rdf:foo
は次のコンポーネントをロードします: @mozilla.org/rdf/datasource;1?name=foo
RDF/XMLデータソースと同様に、この方法で解決されたデータソースは最後の参照が捨てられるまで RDFサービスにより「キャッシュ」されます。
どうやって RDF/XMLファイルからデータソースを作るんですか
RDFサービスの GetDataSource()
メソッドを用いて RDF/XML データソースを作ることができます:
// RDFサービスを得る var RDF = Components .classes["@mozilla.org/rdf/rdf-service;1"] .getService(Components.interfaces.nsIRDFService); // …次にデータソースを得ます。Webブラウザが次のリソースを // '''text/rdf''' で扱うようにしておいてください。 var ds = RDF.GetDataSource("http://www.mozilla.org/some-rdf-file.rdf"); // '''ds'''は非同期にロードされますので、アサーションはすぐには // 利用可能になりません。
または、XPCOM Component Manager を用いて直接作成することもできます。 以下のコード断片はこのやり方を表しています:
// XPCOM Component Manager を使って RDF/XMLデータソースを作る var ds = Components .classes["@mozilla.org/rdf/datasource;1?name=xml-datasource"] .createInstance(Components.interfaces.nsIRDFDataSource); // [http://lxr.mozilla.org/mozilla/source/rdf/base/idl/nsIRDFRemoteDataSource.idl nsIRDFRemoteDataSource]インターフェースは、データソースをセットアップ // する必要のあるインターフェースを提供しています。 var remote = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource); // Webブラウザはこれを'''text/rdf'''として届けること! remote.Init("http://www.mozilla.org/some-rdf-file.rdf"); // ロードします。これは非同期に行われることに注意してください。 // '''aBlocking''' を真にセットすることで同期的に行うことができますが、 // これはえてして悪い考えです。というのも UI が完全にロックされてしまいます。 remote.Refresh(false); // '''ds'''は非同期にロードされますので、アサーションはすぐには // 利用可能になりません。
同期的にロードするために、RDF/XMLデータソースを「手で」作成する必要があると考えるかもしれません。
RDF/XMLデータソースのリロードはどうやるんですか?
RDF/XMLデータソース(または nsIRDFRemoteDataSource
をサポートする全てのデータソース)に対して、 nsIRDFRemoteDataSource
の Refresh()
メソッドを使ってリロードできます。 Refresh()
はオペレーションを同期的に("blocking")または非同期的に("non-blocking")行うよう指定するパラメーターをひとつとります。本当に自分のやることを理解していないなら、同期的にロードするべきではありません: 同期的なロードは完了するまで UI をフリーズします!
RDF/XMLデータソースがロードされたかどうかはどう見分けるんですか?
nsIRDFRemoteDataSource
インターフェースを用いて、データソースがロードされたかそうでないかを loaded
プロパティに即時に尋ねることができます。
// RDFサービスを得る var RDF = Components .classes["@mozilla.org/rdf/rdf-service;1"] .getService(Components.interfaces.nsIRDFService); // データソースを得る var ds = RDF.GetDataSource("http://www.mozilla.org/some-rdf-file.rdf"); // ここで、ロードされたかそうでないか確認… var remote = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource); if (remote.loaded) { alert("データソースはもうロードされています!"); } else { alert("データソースはロードされていません。でもただ今ロードしています!"); }
データソースがロードされていないということは、つまり非同期的にロードを行っているということです。 この API と JavaScript の setTimeout
を用いることで、loaded
プロパティを繰り返しチェックするポーリングループをセットアップできます。 これはクラッジ的(※)で、さらに悪いことにはロードの失敗を検出できません。例えば URL に何のデータも無い場合です! (※訳注 クラッジ(kludge); jargon. その場しのぎ的な安易な方法による問題回避策。とりあえず動くもの。) この理由により、 オブザーバーインターフェース があります。 これはデータソースの進捗を見張れるようにします。以下のコードに使い方を示しています:
// RDF/XML の読み込み進捗を観察するオブジェクト var Observer = { onBeginLoad: function(aSink) {}, onInterrupt: function(aSink) {}, onResume: function(aSink) {}, onEndLoad: function(aSink) { alert("done!"); }, onError: function(aSink, aStatus, aErrorMsg) { alert("error! " + aErrorMsg); } }; // RDFサービスを得る var RDF = Components .classes["@mozilla.org/rdf/rdf-service;1"] .getService(Components.interfaces.nsIRDFService); // データソースを得る var ds = RDF.GetDataSource("http://www.mozilla.org/some-rdf-file.rdf"); // ここで、ロードされたかそうでないか確認… var remote = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource); if (remote.loaded) { alert("データソースはもうロードされています!"); } else { alert("データソースはロードされていません。でもただ今ロードしています!"); // RDF/XML データソースは '''nsIRDFXMLSink''' でもあります var sink = ds.QueryInterface(Components.interfaces.nsIRDFXMLSink); // Observer を sinkとしてのデータソースに関連付けます sink.addXMLSinkObserver(Observer); // '''Observer'''のメソッドがロードの進捗につれてコールバックされます。 }
データソース内の情報へのアクセス方法は?
The nsIRDFDataSource
インターフェースがデータソースのアサーションを扱ったりアクセスしたりする方法です。
boolean HasAssertion(aSource, aProperty, aTarget, aTruthValue)
. これでデータソースが指定されたタップルを持つかどうかをテストします。nsIRDFNode GetTarget(aSource, aProperty, aTruthValue)
.nsISimpleEnumerator GetTargets(aSource, aProperty, aTruthValue)
.nsIRDFResource GetSource(aProperty, aTarget, aTruthValue)
.nsISimpleEnumerator GetSoruces(aProperty, aTarget, aTruthValue)
.nsISimpleEnumerator ArcLabelsIn(aTarget)
.nsISimpleEnumerator ArcLabelsOut(aSource)
.
RDFコンテナ 内の情報にアクセスするためには、 [#how_do_i_manipulate_rdf_containers RDF container] インターフェースを使うこともできます。
データソース内の情報の変更方法は?
RDF/XMLデータソースへの変更を書き戻すにはどうするんですか?
nsIRDFRemoteDataSource
QueryInterface()
Flush()
file:
http:
Flush()
今のところは file: URL のみ Flush() が効くみたいです。(see http://www.geocrawler.com/archives/3/125/2001/10/0/6956391.
いくつかのデータソースを合わせて 1つのように扱うにはどうやりますか?
「組み込み」データソースへはどうやってアクセスしますか?
組み込みデータソースとは、ローカルにインストールされているコンポーネントで、 nsIRDFDataSource. を実装しているものです。 例えば、 ブックマークサービス まず始めに、[#what_is_the_security_model ここ]を見て組み込みデータソースへアクセスできることを確認してください。 信頼されない XUL や JS から、組み込みデータソースへのアクセスする際にはいくつかセキュリティ上の制限があります。 組み込みデータソースはまるっきり XPCOM コンポーネントにすぎませんので、XPConnect コンポーネントマネージャーを用いて直接インスタンス化することができます。
// コンポーネントマネージャーを用いてブックマークサービスを得る var bookmarks = Components. classes["@mozilla.org/rdf/datasource;1?name=bookmarks"]. getService(Components.interfaces.nsIRDFDataSource); // ここに実際に何か行うコードを書く... if (bookmarks.HasAssertion( RDF.GetResource("http://home.netscape.com/NC-rdf#BookmarksRoot"), RDF.GetResource("http://home.netscape.com/NC-rdf#child"), RDF.GetResource("http://home.netscape.com/NC-rdf#PersonalToolbarFolder"), true) { // ... }
また別に、データソースのいくつかは「特別な」RDF向きの ContractID を持っているので、それを nsIRDFSerivce
の GetDataSource()
メソッドや XULテンプレートの datasources
属性に用いてデータソースを簡単にインスタンスにできます。 これらの ContractID は @mozilla.org/rdf/datasource;1?name=name
という形式をしています。 さらに、 GetDataSource()
と datasources
属性 に省略表記の rdf:name
を使ってアクセスすることもできます。 例えば、以下の XUL断片は XULテンプレートにデータソースとしてブックマークサービスを追加する方法を示しています。
<tree datasources="rdf:bookmarks"> ... </tree>
RDF「コンテナ」はどう扱いますか?
RDF「コンテナ」(<rdf:Seq>
など)を扱うためには nsIRDFContainerUtils
が使えます。 IRDFContainerUtils
は以下の ContractID でサービスとしてインスタンス化されます。 @mozilla.org/rdf/container-utils;1
このサービスの IsSeq()
, IsBag()
, IsAlt()
を用いて、あるオブジェクトが RDFコンテナであるかどうかを判別できます。 まだ
MakeSeq()
, MakeBag()
, MakeAlt()
を使われていない「リソースをコンテナに格納」できます。 これらのメソッドは nsIRDFContainer
を返し、このインターフェースで手間をかけずにコンテナライクな操作ができます。 また別のやり方として、もしデータソースが既に RDFコンテナであるオブジェクトを持っているならば、nsIRDFContainer
オブジェクトを @mozilla.org/rdf/container;1
な ContractID でインスタンス化し、データソースとリソースをパラメータに Init()
することができます。 このやり方は、リソースが既にコンテナでない場合は失敗することに注意してください。
2. XULテンプレート
XULテンプレートは XULドキュメント中の
datasources
で指定される属性で作成されます。 XULテンプレートを書くには 2通りの「形式」があります。 Mozillaコードベースで現在のところ最も一般的に使われている「簡易」形式と、RDFグラフに対して洗練されたマッチングを可能にする「拡張」形式です。 「簡易」形式は XUL Template Reference で議論されています。 「拡張」形式は XUL Template Primer で議論されています。 (これはやや変な扱い方です。というのも、最終的な目的は、概念的にはより簡単な拡張形式を用いてテンプレートを紹介し、後に「簡易」形式を拡張形式の省略記法として扱うことだからです。)
XULテンプレートで構築できる内容はどんなものですか?
あらゆる種類の内容を XULテンプレートを用いて構築することができます。 primer にあるほとんどのサンプルは treeウィジェットが使われていますが、
<rule>
中の <action>
節にはどんなタグ(HTML や任意の XML も含みます)も使うことができます。
どんな時に XULテンプレートを利用すべきですか?
RDF と XULテンプレートを使うやり方の代替手段ひとつは、 W3C DOM APIs を使って XUL(や HTML) コンテントモデルを構築・操作することです。 ですが、これには不都合な時がままあります:
データには様々な「見せ方」があります。 For example, Mozilla mail/news reveals the folder hierarchy in the toolbar, the "folder pane", in several menus, and in some of the dialogs.
<menubutton>
、<menu>
,<tree>
それぞれの DOMツリーを構築するために 3つの JS(か C++)コードを書くよりも、各内容モデルに対してひとつづつ、計 3つのコンパクトなルール集合を書く方がよいでしょう。データは変わります。 たとえば、mail/news ユーザーは IMAP フォルダを追加したり削除したりします。 (この要求が内容モデルを構築するのをどんなに面倒にすることか!) XULテンプレートビルダはルールを使って、全ての内容モデルを変化に自動的に同期させます。
もちろんこの機能を活用するためには情報を RDF datasource API, の規約で表現できなければなりません。 これは、組み込みのメモリデータソースを使ったり、情報を格納するのに RDF/XML を使ったり、自分で
nsIRDFDataSource
の実装を(たぶん JavaScript で)書くことで行います。
"datasources=" に指定したら何がロードされるんですか?
ロードしたいデータソースURIを空白で区切ったリストを、 テンプレートの「ルート」にある
datasources
属性に指定します。 でも「データソースURI」とは何なのでしょうか? それは、以下のいずれかです:
ローカルにインストールされているコンポーネントの ContractID の省略表記です。
rdf:name
で指定することで、テンプレートビルダに@mozilla.org/rdf/datasource;1?name=name
という ContractID の XPCOMコンポーネントをロードするよう指示します。RDF/XML ファイルの URL です。例えばこんなもの:
file:///tmp/foo.rdf
chrome://mycomponent/content/component-data.rdf
http://www.mysite.com/generate-rdf.cgi
ftp://ftp.somewhere.org/toc.rdf
ロードは非同期に行われます。 RDF/XML が届けられるにつれて、テンプレートビルダは内容を生成します。 どの場合でも、データソースは
nsIRDFService
の GetDataSource()
メソッドを用いてロードされます。 ですので、この方法によりロードされる他のデータソース全てと同じように [#how_does_mozilla_manage 管理] されます。
XUL の RDF/XML のセキュリティモデルはどんなものですか?
「信頼された」URL(今のところ
chrome:
URLの全て)からロードされた XUL は、XULテンプレートの datasources
属性にあらゆるデータソースURI を指定できます。 「信頼されていない」URLからロードされた XUL は、その XUL ドキュメントが由来したのと同じ (Java流に言えば)codebase からの RDF/XML ドキュメントのみを指定できます。 信頼されないXUL は「特殊な」(すなわちrdf:
)データソースをロードできません。
XULテンプレートにデータソースを追加するにはどうやりますか?
XULテンプレートを
datasources
属性に指定された「暗黙の」データソース集合と共に生成できますが、 XULがロードされた後で加えたいデータソースが分かる場合がしばしばあります。 たとえば、表示したいデータソースを onload
ハンドラで計算する必要があるかもしれませんし、ユーザーのアクションによって後からデータソースを加える必要があるかもしれません。 どうやってこれを行うのかを示した簡単な例を示します。 以下の XUL を見てください。
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
...
<tree id="my-tree" datasources="rdf:null">
...
</tree>
...
</window>
どうにかしてデータソースを得たとします(例えば [#how_do_i_create_rdfxml こう]やって)。 以下のサンプルコードに、どうやってこのデータソースをテンプレートに追加し、その新たなデータソースの内容に基いてテンプレートを再構築するのかを示します。
var ds = /* とにかく得ました! */;
// 'my-tree' の DOMエレメントを得ます
var tree = document.getElementById('my-tree');
// データソースを加えます
tree.database.AddDataSource(ds);
// ここで tree を再構築します。「手動で」行わなければいけません!
tree.builder.rebuild();
datasources
を持った XULエレメントは全て database
プロパティと builder
プロパティを「獲得」します。 database
プロパティは nsIRDFCompositeDataSource
オブジェクトを参照していて、ここにテンプレートを構築したデータソースが含まれています。 builder
プロパティは nsIXULTemplateBuilder
オブジェクトを参照していて、これはテンプレート内容の状態を維持する「ビルダ」です。 ところで rdf:null
データソースというものがあります: これは特殊なデータソースで、「まだデータソースは無いぜ。だが後から加えるから準備しといてくれ!」と言ってることになります。 これで database
と builder
プロパティがインストールされますが、database
は空のデータソース集合になっています: あとで自分で追加します!
XULテンプレートは DOM API で扱えますか?
できます: ルールを追加したり削除したり、ルールの条件を変更したり、ルールから構築される内容を変更することができます。 実際には、 W3C DOM APIs を使って、テンプレートに関するあらゆるものを変更できます。 ひとつ注意しておくことは、(XULテンプレートに [#how_do_i_add_datasource データソースを追加する] ためにしなければならないのとまったく同じように、)変更が効果を表すためには
rebuild()
を呼ばなければならないということです。
テンプレートからのデータをプレーンテキストとして差し込むにはどうやりますか?
テンプレートにプレーンテキストを挿入するには、
<text>
エレメントを使います。
<template>
<rule>
<conditions>...</condition>
<bindings>...</bindings>
<action>
<text value="?some-variable" />
</action>
</rule>
</template>
上のテンプレートは一連のテキストノードと共に稼働する内容モデルを作成します。
3. うまくいかなかったら
実地から得られた trick や tips です。
RDF/XMLファイルがロードされない
Webサーバーから RDF/XML がロードされない理由の一番よくある原因は、MIME型が間違っていることです。サーバーが RDF/XMLファイルを
text/rdf
で配布していることを確認してください。 RDF/XML が実際に妥当<valid>であることを確認するためには rdfcat
や rdfpoll
ユーティリティを利用できます。 これら両方のプログラムともデフォルトでは Windows で構築されます。Linux では configure --enable-tests
を指定してください。
rdfcaturl
と指定します。パラメーターの指定した URL から RDF/XML ファイルを読み込み、コンソールに「表示<cat>」します。これを使って、あなたの書いた RDF/XML が Mozilla によってパーズされているかを確認できます。rdfpollurl [interval]
と指定します。 パラメーターに読み込む RDF/XML ファイルの URL を指定します。 オプションで URL をリロードするポーリング間隔 をとります。 各ロードで生成されたアサーションを出力します。 ポーリングリロードは、今回と前回との RDF/XMLファイル内容の差分集合を生成することに注意してください。 これは、動的に生成され時間的に変化する RDF/XML ファイルをデバッグするのに有用です。
これらのプログラムはロードと実行が遅いです(でも最終的には動くでしょう)。 これらは XPCOM を初期化し、ロードと URLの処理ができるよう Necko を準備します。ちょうど Mozilla がやってるのと同じです。
Notes
Original Document Information
Contributors
Author(s): Chris Waterson
Last Updated Date: December 22, 2004
Copyright Information: Copyright (C) Chris Waterson