Account Auto-DiscoveryとTrackBack Auto-Discoveryを合わせる

自サイトに、以下のようなAccount Auto-Discovery用のRDFを埋め込むことを考えてみます。

<rdf:RDF
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:foaf="http://xmlns.com/foaf/0.1/">
  <rdf:Description rdf:about="http://www.akatsukinishisu.net/itazuragaki/itazura/i20050729.html">
    <foaf:maker rdf:parseType="Resource">
      <foaf:holdsAccount>
        <foaf:OnlineAccount foaf:accountName="kits">
          <foaf:accountServiceHomepage rdf:resource="http://www.hatena.ne.jp/" />
        </foaf:OnlineAccount>
      </foaf:holdsAccount>
    </foaf:maker>
  </rdf:Description>
</rdf:RDF>

もしWeblogツールを使用しているのであれば、以下のようなTrackBack Auto-Discovery用のRDFが既に埋め込んであることも多いでしょう。

<rdf:RDF
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <rdf:Description
    rdf:about="http://www.akatsukinishisu.net/itazuragaki/itazura/i20050729.html"
    dc:identifier="http://www.akatsukinishisu.net/itazuragaki/itazura/i20050729.html"
    dc:title="2005年7月29日"
    trackback:ping="http://www.akatsukinishisu.net/itazuragaki/itazura/i20050729.tb"/>
</rdf:RDF>

Account Auto-Discovery用のRDFもTrackBack Auto-Discovery用のRDFも、どちらも記事のURIを主語としたRDFなので、どうせならまとめて1つのRDFで記述してみたいところです。例えば以下のように。

<rdf:RDF
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"
  xmlns:foaf="http://xmlns.com/foaf/0.1/">
  <rdf:Description
    rdf:about="http://www.akatsukinishisu.net/itazuragaki/itazura/i20050729.html"
    dc:identifier="http://www.akatsukinishisu.net/itazuragaki/itazura/i20050729.html"
    dc:title="2005年7月29日"
    trackback:ping="http://www.akatsukinishisu.net/itazuragaki/itazura/i20050729.tb">
    <foaf:maker rdf:parseType="Resource">
      <foaf:holdsAccount>
        <foaf:OnlineAccount foaf:accountName="kits">
          <foaf:accountServiceHomepage rdf:resource="http://www.hatena.ne.jp/"/>
        </foaf:OnlineAccount>
      </foaf:holdsAccount>
    </foaf:maker>
  </rdf:Description>
</rdf:RDF>

実際、これをRDF Validation Serviceに掛けてみたところ、妥当なRDFとして解釈されたようなので、理論的には問題なさそうに思えます。

問題は実際使われているツールがこの記述を解釈してくれるか、というところですが、実際にMovable Typeのクイックポスト(bookmarkletによる投稿)と、はてなブックマークでのポイント送信を試したところ、どちらも上記の記述で問題なく解釈してくれているようでした。

ちなみに、MTでは以下のような処理でTrackBack Auto-Discoveryしているようです。

    while ($c =~ m!(<rdf:RDF.*?</rdf:RDF>)!sg) {
        my $rdf = $1;
        my($perm_url) = $rdf =~ m!dc:identifier="([^"]+)"!;   #"
        next unless $find_all ||
            $perm_url eq $url || $perm_url eq $url_no_anchor;
        (my $inner = $rdf) =~ s!^.*?<rdf:Description!!s;
        my $item = { permalink => $perm_url };
        while ($inner =~ /([\w:]+)="([^"]*)"/gs) {            #"
            $item->{$1} = $2;
        }
        $item->{ping_url} = $item->{'trackback:ping'};
        next unless $item->{ping_url};

また、HTML-AccountAutoDiscovery-0.05では以下のような処理をしていました。

    while ( $$sp =~ m{(<rdf:RDF.*?</rdf:RDF>)}sg) {
        my $rdf = $1;
        my $foaf = '';
        if ( $rdf =~ m{xmlns:(\w+)="$foafuri"}o ) {
            $foaf = $1 . ':';
        } elsif ( $rdf =~ m{xmlns="$foafuri"}o ) {
            $foaf = '';
        } else {
            next;
        }
        while ( $rdf =~ m{<(${foaf}holdsAccount)(.*?)</\1>}sg ) {
            my $onlineaccount = $2;
            my( $servicehomepage, $accountname );
            if ( $onlineaccount =~ m{
                                     <${foaf}accountServiceHomepage[^>]+rdf:resource="(.*)"
                                 }xs ) {
                $servicehomepage = $1;
            }
            if ( $onlineaccount =~ m{
                                     <${foaf}accountName>[\s\n]*([^<>]+)[\s\n]*</${foaf}accountName>
                                 }xs ) {
                $accountname = $1;
            }
            if ( $onlineaccount =~ m{${foaf}accountName="([^<>]+?)"} ) {
                $accountname = $1;
            }
            if ( defined( $servicehomepage ) && defined( $accountname ) ) {
                $yield->( $servicehomepage, $accountname );
            }
        }
    }

要は、どちらもRDFをXMLとして解析しているわけでなく、正規表現による検索で trackback:ping="url"accountName="ID" 等を拾っているので、規定の記述から大きく外れていなければ何とか解釈してくれそうな感じです。

……というわけで、昨日より徒書の各記事にこのようなRDFを埋め込んでいます。ちなみに今のところはまだ妥当なXHTML 1.1文書としておきたいので、コメントとして埋め込んでおります。

参考リンク