RDFデータソースの使い方
RDFデータソースの使い方について簡単にまとめてみました.
RDFデータソースはFirefoxでデータを扱う上で重要な要素で,
ブックマークや履歴など様々な場所で利用されている.
XUL の tree 要素を使用する場合にはほぼ必須です.
RDFについて
RDFは,
subject ----> [predicate(property)] ---> target
という関係を表す.
これをトリプル (triple) と呼ぶ.
<subject> <predicate>target</predicate> </subject>
とか,
<subject predicate="target" />
とか.
subjectにはリソースの場所を表すためのURIが必要.
URI には, URL や URN などが用いられる.
<subject rdf:about="urn:hoge" predicate="target" /> <subject rdf:about="http://d.hatena.ne.jp/ao3/subjecgt1" predicate="target" />
subject には複数の predicate を設定可能.
<subject predicate1="target1" predicate2="target2" />
コンテナモデルもある.
※追記: コンテナモデルのRDF/XML表現が間違ってたので修正.
container -- 1:* --> [rdf:li] ---> subject
コンテナの種類には,
がある.
<rdf:Seq rdf:about="urn:subjects"> <rdf:li><subject predicate="target1" /></rdf:li> <rdf:li><subject predicate="target2" /></rdf:li> <rdf:li><subject predicate="target3" /></rdf:li> </rdf:Seq>
このとき, URI を利用して, ほかの subject を参照可能.
<rdf:rdf xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Seq rdf:about="urn:subjects"> <rdf:li rdf:resource="urn:hoge:1" /> <rdf:li rdf:resource="urn:hoge:2" /> <rdf:li rdf:resource="urn:hoge:3" /> </rdf:Seq> <subject rdf:about="urn:hoge:1" predicate="target1" /> <subject rdf:about="urn:hoge:2" predicate="target2" /> <subject rdf:about="urn:hoge:3" predicate="target3" /> </rdf:rdf>
通常, subject, predicate は独自定義する場合, XML-namespace をつける.
<rdf:rdf xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:nc1="http://d.hatena.ne.jp/ao3/person#"> <rdf:Seq rdf:about="urn:persons"> <rdf:li rdf:resource="urn:persons:1" /> <rdf:li rdf:resource="urn:persons:2" /> <rdf:li rdf:resource="urn:persons:3" /> </rdf:Seq> <nc1:person rdf:about="urn:persons:1" nc1:name="hoge" nc1:age="12" /> <nc1:person rdf:about="urn:persons:2" nc1:name="foo" nc1:age="32" /> <nc1:person rdf:about="urn:persons:3" nc1:name="boo" nc1:age="91" /> </rdf:rdf>
使用する XPCOM のサービス
nsIRDFService
データソースの要素 (nsIRDFNode, nsIRDFResource) を取得するために用いる.
var RDFService = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
nsIRDFContainerUtils
コンテナ(nsIRDFContainer)を作成・判別するために用いる.
var RDFContainerUtils = Cc["@mozilla.org/rdf/container-utils;1"] .getService(Ci.nsIRDFContainerUtils);
データソースの使用方法
nsIRDFDataSource インタフェースを実装したオブジェクトを用いる.
データソースを処理し, 必要なデータを読み取る方法について説明する.
URI からデータソースを読み込み
var ds = RDFService.GetDataSource("http://d.hatena.ne.jp/ao3/hoge.rdf");
非同期で読み込まれるので ds.loaded が true になるまでは, データがすべて存在するか不明.
URI から読み込んだデータソースを再読み込み
ds.QueryInterface(Ci.nsIRDFRemoteDataSource);
ds.Refresh(false);
Refresh(false) は非同期読み込み. Refresh(true) はブロッキング読み込み.
非同期で読み込むことが推奨されるとのこと.
ArcLabelsIn
指定したリソースを保持しているノード(親ノード?)の一覧を返す.
ArcLabelsOut
指定したリソースの子ノードの一覧を返す.
GetTarget, GetTargets
データソースに対して, subject, predicate を指定して, それに属する target を取得する.
subject --- [predicate] --- >> target <<
var baseURI = "http://d.hatena.ne.jp/ao3/rdf#"; var subject = RDFService.GetResource("urn:datas:1"); var predicate = RDFService.GetResource(baseURI + "text"); var target = ds.GetTarget(subject, predicate, true);
predicateは, nc1:text のような namespace を使った定義ができないため,
URIを絶対パス(?)で記述する必要がある.
途中までを定数などにおいておくと記述が楽になる.
GetSoruce, GetSources
データソースに対して, predicate, target を指定して, それを保持する subject を取得する.
>> subject << --- [predicate] --- target
var baseURI = "http://d.hatena.ne.jp/ao3/rdf#"; var predicate = RDFService.GetResource(baseURI + "text"); var target = ds.GetLiteral("foo"); var subject = ds.GetTarget(predicate, target, true);
コンテナモデル
nsIRDFContainer, nsIRDFContainerUtils を使う.
var ds; // とにかく データソース がある. var containerResource = RDFService.GetResource("urn:datas"); // コンテナのURI // コンテナモデルか判定する if (! RDFContainerUtils.IsContainer(ds, containerResource) ) { return false; } // containerResource をコンテナモデルとして初期化 var container = Cc["@mozilla.org/rdf/container;1"] .createInstance(Ci.nsIRDFContainer); container.Init(ds, containerResource); // コンテナに属するノードを列挙 var sources = container.GetElements(); while(sources.hasMoreElements()) { var subject = sources.getNext().QueryInterface(Ci.nsIRDFResource); var predicate = RDFService.GetResource(baseURI + "text"); var target = ds.GetTarget(subject, predicate, true); }
独自のデータソースの作成方法
データソース作成
var ds = Cc["@mozilla.org/rdf/datasource;1?name=in-memory-datasource"] .createInstance(Ci.nsIRDFDataSource);
リソース作成
subject, predicate を作成する際に用いる.
var resource = RDFService.GetResource("urn:datas");
リテラル作成
target を作成する際に用いる. GetLiteral() 以外は使ったことがないので動作は不明.
var literal = RDFService.GetLiteral("foo"); var intLiteral = RDFService.GetIntLiteral(1); var dateLIteral = RDFService.GetDateLiteral(new Date()); // これでいいか不明
トリプル作成
const baseURI = "http://d.hatena.ne.jp/ao3/rdf#"; var subject = RDFService.GetResource("urn:datas:1"); var predicate = RDFService.GetResource(baseURI + "text"); var target = RDFService.GetLiteral("hogehoge"); ds.Assert(subject, predicate, target, true);
コンテナモデルの利用
nsIRDFContainerUtils を利用する.
// container を作成 var containerResource = RDFService.GetResource("urn:datas"); var container = RDFContainerUtils.MakeSeq(ds, containerResource); // container に subject を追加 var subject = RDFService.GetResource("urn:datas:1"); container.AppendElement(subject); // subject に predicate を追加 ds.Assert(subject, RDFService.GetResource(baseURI + "text"), RDFService.GetLiteral("hogehoge"), true );
データソースをファイル (RDF/XML) へ保存
// 書き出すファイル var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); file.initWithPath("c:\\dump.rdf"); // 出力ストリーム var fos = Cc["@mozilla.org/network/file-output-stream;1"] .createInstance(Ci.nsIFileOutputStream); fos.init(file, -1, -1, 0); try { // シリアライザ var serializer = Cc["@mozilla.org/rdf/xml-serializer;1"] .createInstance(Ci.nsIRDFXMLSerializer); // DataSourceのセット serializer.init(dataSource); // 書き出し serializer.QueryInterface(Ci.nsIRDFXMLSource); serializer.Serialize(fos); } finally { fos.close(); }