Hatena::Groupweb

vantguarde

11.23

RDFaでFOAFを書く

| 14:12

また変なXHTMLを見つけたので。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
 "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html version="XHTML+RDFa 1.0"
 xmlns="http://www.w3.org/1999/xhtml"
 xmlns:foaf="http://xmlns.com/foaf/0.1/"
 xmlns:dc="http://purl.org/dc/terms/">
<head typeof="foaf:PersonalProfileDocument">
  <title property="dc:title">profile</title>
  <link rel="foaf:maker" resource="[_:vantguarde]"/>
  <link rel="foaf:primaryTopic" resource="[_:vantguarde]"/>
</head>
<body>
<h1>profile: vantguarde</h1>
<dl about="[_:vantguarde]" typeof="foaf:Person">
  <dt>Name:</dt>
  <dd property="foaf:nick">vantguarde</dd>
  <dt>Email:</dt>
  <dd><a rel="foaf:mbox" href="mailto:vantguarde@example.com">vantguarde@example.com</a></dd>
  <dt>Weblog:</dt>
  <dd><a rel="foaf:weblog" href="http://web.g.hatena.ne.jp/vantguarde/">vantguarde</a></dd>
  <dt>Birthday:</dt>
  <dd property="foaf:birthday" content="03-19">19 Mar. 1998</dd>
  <dt>Twitter:</dt>
  <dd rel="foaf:holdsAccount"><a rel="foaf:isPrimaryTopicOf" href="http://twitter.com/vant">twitter.com/vant</a></dd>
  <dt>Skype:</dt>
  <dd rel="foaf:phone" resource="callto://vantguarde">vantguarde</dd>
</dl>
</body>
</html>

RDFaで覚えておくのは次くらいでしょうか。

  • CURIE(QNameっぽくURIを書ける。ブラケットで囲むとsafe CURIEに。)
  • 匿名ノード(アンダースコアがprefixなCURIE。込み入った表現をしたいときにほぼ必須。)
  • @aboutと@resourceはURIまたは匿名ノードをとる。
  • @rel, @revはpredicateを表現。@propertyはリテラル用のpredicate。
  • @rel, @revはRDFaで@about/@resourceに対するpredicateとしてスコープが変更。
  • @hrefなどもリソースとして使われる。
  • @typeofはrdf:typeと等価。
  • chainingというルールがあって、それを使えばいろいろまとめられる。

けっこう多かった。まあでもRDFわかる人ならすぐですね。

foaf.rdfというブラウザーで開けないファイルよりは、RDFa+FOAFなプロファイルページにするのがいいのかなあと思ったりしています。

1.25

FOAFつくってみた

| 20:40

評判のオントロジーとFOAFというスライドが公開されていたので、久しぶりにやってみるかとFOAFを作ってみました。前のがどこにあったか分かんないので、見つけ次第リンクでもしておきます。

@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl:  <http://www.w3.org/2002/07/owl#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc:   <http://purl.org/dc/elements/1.1/> .
@prefix dct:  <http://purl.org/dc/terms/> .

<tag:lepetitcroissant@gmail.com,2007:me:foaf> a foaf:PersonalProfileDocument ;
  foaf:maker <tag:lepetitcroissant@gmail.com,2007:me> ;
  foaf:primaryTopic <tag:lepetitcroissant@gmail.com,2007:me> ;
  dct:issued "2007-01-25";
  dct:created "2007-01-25" .

<tag:lepetitcroissant@gmail.com,2007:me> a foaf:Person ;
  foaf:mbox <mailto:lepetitcroissant@gmail.com> ;
  foaf:weblog <http://web.g.hatena.ne.jp/vantguarde/> , <http://d.hatena.ne.jp/vantguarde/> ;
  foaf:birthday "3-19" .

tagURIで僕自身およびPPDにURIをふっておきました。PPDに関してはたぶんHTTPで取得可能なリソースが好ましい気がするので、どこか場所を見つけてアップしたいと思います。

RDF/XMLを書くのが面倒だったのでTurtleで書いてます。RDF Validator and ConverterにかけてValidなものだと判断されてます。

4.20

foaf:PersonalProfileDocument

| 16:09

はい、メインのトピックはわかったよ。でもprimaryTopicのみじゃ、誰がそれを言ったのか分からない。なので結局「僕のFOAF」は表現できないんじゃないのか、という問題です。

それを解決するのがfoaf:PersonalProfileDocumentというクラスと、foaf:maker, foaf:primaryTopicの組み合わせによる「これは僕がメインで、僕によって作られた僕のプロフィールです。」という文。

foaf:PersonalProfileDocumentクラスは「この文書を作ったひと(foaf:maker)に関するプロフィール文書」という意味を持つもの。

@prefix foaf: <http://xmlns.com/foaf/0.1/> .

<> a foaf:PersonalProfileDocument ;
  foaf:maker _:vant ;
  foaf:primaryTopic _:vant .

_:vant a foaf:Person ;
  foaf:name "vant" ;
  foaf:weblog <http://web.g.hatena.ne.jp/vantguarde/> ;
  foaf:knows _:friend .

_:friend a foaf:Person ;
    foaf:name "friend" ;
    foaf:weblog <http://example.com/friend> .

foaf:makerも、foaf:primaryTopicもvantを指してます。なので「これはvantが作った自身のプロフィールで、もちろんメインのトピックはvantの情報」という意味になるわけです。これにて解決。

ちなみにfoaf:primaryTopic, foaf:isPrimaryTopicOf, そしてfoaf:PersonalProfileDocumentはFOAFブームが起こった後に追加されたので、その時手書きでFOAFを書いてた人はちょっと見直した方がいいかも。というのは、「これ僕が書いたぼくのFOAFだよ」ということをFOAFブームの頃のスキーマでは示せなかったから。なので今編集する気のある人はつけくわえといてね。

foaf:primaryTopic/foaf:isPrimaryTopicOf

| 15:58

前回の続き。個人の情報とそのファイルにつながりがないとはどういうことか、ってことを書こうと思ったんだけど、ちょっと理解不足かもということで、とりあえず解答を。逃げっ。

# http://example.com/foaf

@prefix foaf: <http://xmlns.com/foaf/0.1/> .

_:vant a foaf:Person ;
  foaf:name "vant" ;
  foaf:weblog <http://web.g.hatena.ne.jp/vantguarde/> ;
  foaf:knows _:friend .

_:friend a foaf:Person ;
    foaf:name "friend" ;
    foaf:weblog <http://example.com/friend> .

さて、これだと僕のFOAFなのかfriendのFOAFなのか、RDF的にはっきりしないわけです。そこで登場するのが、このURLと僕を結びつけるプロパティ、foaf:primaryTopic又はfoaf:isPrimaryTopicOf。

foaf:primaryTopicは「主語のリソースが持つメインのトピックはこのリソース」というのを示すプロパティで、foaf:isPrimaryTopicOfはその反対「主語のリソースをメインとするリソース」を示すプロパティ。わかりにくいですね、というわけで例を。

@prefix foaf: <http://xmlns.com/foaf/0.1/> .

<> foaf:primaryTopic _:vant .

_:vant a foaf:Person ;
  foaf:name "vant" ;
  foaf:weblog <http://web.g.hatena.ne.jp/vantguarde/> ;
  foaf:knows _:friend .

_:friend a foaf:Person ;
    foaf:name "friend" ;
    foaf:weblog <http://example.com/friend> .

<> foaf:primaryTopic _:vant .を入れただけ。<>は「この文書」という意味、つまりこの場合<http://example.com/foaf>と等価です。「http://example.com/foafのメイントピックはvantに関する情報だよ。」ということを言ってるわけです。

で、foaf:isPrimaryTopicOfを使うとこうなる。

@prefix foaf: <http://xmlns.com/foaf/0.1/> .

_:vant a foaf:Person ;
  foaf:name "vant" ;
  foaf:weblog <http://web.g.hatena.ne.jp/vantguarde/> ;
  foaf:knows _:friend .

_:vant foaf:isPrimaryTopicOf <> .

_:friend a foaf:Person ;
    foaf:name "friend" ;
    foaf:weblog <http://example.com/friend> .

「vantに関する情報はhttp://example.com/foafのメイントピックだよ。」ということになります。主語と目的語が入れ替わってますが、同じ意味ですよね。二つのプロパティはowl:inverseで関係づけられてるので、どちらを用いても「誰がメイントピックか」を示せます。

ただRDF/XMLを考えると、foaf:isPrimaryTopicOfの方がいいかも。

<rdf:RDF xmlns...>
  <rdf:Description rdf:about="">
    <foaf:primaryTopic rdf:nodeID="vant"/>
  </rdf:Description>

  <foaf:Person rdf:nodeID="vant">
    <foaf:name>vant</foaf:name>
    <!-- のこり省略 -->
  </foaf:Person>
</rdf:RDF>

foaf:primaryTopicを使うと、rdf:Description要素をfoaf:Personの兄弟要素にしないといけない。で、FOAFをただのXMLとして解析するアプリがもしかしたらそれを上手く扱ってくれないかもしれないから。

<rdf:RDF xmlns...>
  <foaf:Person>
    <foaf:name>vant</foaf:name>
    <!-- のこり省略 -->
    <foaf:isPrimaryTopic rdf:resource=""/>
  </foaf:Person>
</rdf:RDF>

foaf:isPrimaryTopicOfだとfoaf:Personの子要素として収められるので、見た目を気にする人にもいいかも。

ただ、もう一つ問題が。それはメインのトピックが分かったからといって、誰がそれを言ったのか分からないこと。

4.17

SPARQLメモとFOAF

| 16:40

引き続きSPARQLのお勉強。今日は名前を抜き出してみます。

PREFIX foaf: <http://xmlns.com/foaf/0.1/>

SELECT ?name
WHERE {
  ?p a foaf:Person ;
    foaf:name ?name ;
}
ORDER BY ?name

ORDER BYは続く変数で結果をソートする為のキーワード。

で、こう帰ってくる。

<sparql ...>

  <head>
    <variable name="name"/>
  </head>

  <results>

    <result>
      <binding name="name">
        <literal>Another Friend</literal>
      </binding>
    </result>

    <result>
      <binding name="name">
        <literal>My Friend</literal>
      </binding>
    </result>

    <result>
      <binding name="name">
        <literal>vant</literal>
      </binding>
    </result>

  </results>
</sparql>

はい、3つでてきました。元のFOAFにはぼく、My Friend, Another Friendの3人の情報(名前)があるので、3つ帰ってきます。

では、「あるFOAFファイルがあって、そのメインとなる人」の情報のみを返したい場合どうするか?

おとといのFOAFを見るに、どうやら僕がその人らしい。ただ、あのFOAFでは「僕のFOAF」だと確実にいうことが出来ないんです。もしかしたらMy Friendがメインかもしれないし、Another Friendがメインかもしれない。

これはFOAFにおいて、個人の情報とそれを記述したファイルとの間につながりがないことで引き起こされる問題です。

Contact: @vant / lepetitcroissant@gmail.com.