RDF/XML構文の簡単な説明

リソース表現のフレームワークであるRDFのモデルは、一般にXMLとして記述して利用します。この構文では、同じモデルを異なった方法で記述できるので、多少混乱するかも知れません。RDF/XML構文の基本ルールと、それから導かれる省略記述方法を説明します。

RDFをXMLで表現する

RDFは、主語[S]となるリソースを、述語[P]と目的語[O]によって表現します。RDFのモデルは、[S][O]ノードとし、[P]をこれらを結ぶアークとする有向ラベル付きグラフとして表されます[RDFMS]。このとき、目的語[O]がリソースである場合は、その目的語を主語にした別の文(Statement)が続くという、連鎖型のモデルをとることができ、グラフとしては、ノードアークノードアーク…という連鎖が示されます。また、同じ主語に対する複数の文を表現するために、一つのノードから複数のアークが伸びるモデルもあります。

たとえば、ある書籍の著者名とそのホームページを示すRDFモデルは、次のグラフで表現できます。

<書籍urn:isbn>--<dc:creator>--<O=S>--<ex:name>-->[Kanzaki]; <O=S>--<ex:homePage>--><homePage:uri>

このRDFをXMLとして表現する基本的な方法は、次のようなものです。

  1. 主語[S]と述語[P](ノードとアーク)の連鎖は、ノードを示すrdf:Description要素とアークを示すプロパティ要素を交互に記述し、入れ子のXML構造として表現します。この構文は、ノード要素とプロパティ要素がサンドイッチ型になっているため、「ストライピング」と呼ばれます[STRIPE]

  2. 主語が複数の述語を持つ(ノードから複数のアークが伸びる)場合は、ノード要素(rdf:Description)内に複数のプロパティ要素を列挙します。

この考えによって、上のグラフは次のようにXMLとして記述できます。

[例1]

 1: <rdf:RDF xmlns...>
 2:  <rdf:Description rdf:about="urn:isbn:4-8399-0454-5">
 3:   <dc:creator>
 4:    <rdf:Description>
 5:     <ex:name>KANZAKI, Masahide</ex:name>
 6:     <ex:homePage>
 7:      <rdf:Description rdf:about="http://kanzaki.com">
 8:      </rdf:Description>
 9:     </ex:homePage>
10:    </rdf:Description>
11:   </dc:creator>
12:  </rdf:Description>
13: </rdf:RDF>

RDF/XML構文のいくつかのルールを組み合わせることで、このXMLは次のように簡略化することも可能です。

[例2]

<rdf:RDF xmlns...>
 <rdf:Description rdf:about="urn:isbn:4-8399-0454-5">
  <dc:creator rdf:parseType="Resource">
   <ex:name>KANZAKI, Masahide</ex:name>
   <ex:homePage rdf:resource="http://kanzaki.com"/>
  </dc:creator>
 </rdf:Description>
</rdf:RDF>

例1と例2で見たとおり、RDF/XML構文では一つのモデルを複数の方法で記述できるようになっています。どうすればこういう省略構文が書けるのか、どんな構文が正しく、どんなものが認められないのかを理解するために、RDF/XML構文のルールをかいつまんで紹介します。

〔補足〕 本稿の例では名前空間の宣言は省略しますが、rdf:はRDF-MSの名前空間を指すものとします。その他の接頭辞は、単なる例なので、どんな名前空間に結びつけてもモデルを考える上での違いはありません。いちおう、dc:Dublin Coreh:はXHTML、ex:は任意の例(http://example.com/ex/など)を念頭に置いています。

XML構文のモデル生成規則

RDF/XML構文仕様書[RDF/XML]の改訂版草案では、省略形式を含めた基本構文についての説明がかなり拡充されました。それでも、どんなときにどんな省略が可能なのかをきちんと理解するには、セクション7のRDF/XML Grammerで定められる生成規則を見て、そこから逆に考えていく必要があります。まずこのセクションでは、主要な生成規則の概要を取り上げることにします。

ノード要素の生成規則

RDFは主語となるリソースについての記述なので、(ルートのrdf:RDF要素の次のレベルは)主語を示すノード要素で始まります。単純化したノード要素の文法は、次のようなものです。

<nodeElt ((rdf:ID|rdf:about|rdf:nodeID)="S")? propertyAttr*>
 propertyEltList
</nodeElt>

つまり、nodeEltで表されるノード要素は、主語Sを示すrdf:IDもしくはrdf:about属性(nodeIDは空白ノードとなる特別なID)を0もしくは1つと、任意の数のpropertyAttr(プロパティ属性)を持ち、子要素にpropertyEltListプロパティ要素リスト)を含む、というものです。抽象的でやや分かりにくいと思いますが、例を挙げながら、ここからモデルを導くルールを説明します。

ノードの主語URIの決定

まず、主語となるリソースのURI(s.URI)を、次のルールで導きます:

  • rdf:ID属性がある場合は、s.URI= baseURI + '#' + S
  • rdf:about属性がある場合は、s.URIはその値(s.URI=S)
  • rdf:nodeID属性があるか、それ以外の場合は、空白ノードを生成してローカルID(bnodeID)を付与(rdf:nodeIDがあればその値)

例えば、[例1]の2行目ならs.URIurn:isbn:4-8399-0454-5、4行目は空白ノードでbnodeIDが付与されます。

モデルの生成

開始タグ(および子要素)に記述されている情報を元に、次のルールを適用してモデルを生成し、ノードに付加していきます。

[N1] 型付きノード(Typed Node)からの文の生成

nodeEltrdf:Descriptionない場合は、rdf:typeプロパティの値(目的語)をこの要素型名とする文をモデルに加えます。つまり、この主語は「要素型名クラス」のリソース(インスタンス)として扱われます。たとえば、次のタグ:

(例) <ex:Music rdf:about="urn:isbn:0-393-09770-8">

これはurn:...を主語、rdf:typeを述語、ex:Musicを目的語としたモデル、すなわちこの主語リソースがex:Musicクラスのインスタンスであることを意味します。

<s.URI> --- <rdf:type> ---> <nodeElt.URI>

[N2] rdf:type属性からの文の生成

propertyAttrの中にrdf:type属性があれば、その値を使って、上記[N1]と同じグラフをモデルに加えます。

(例) <rdf:Description rdf:about="urn:isbn:0-393-09770-8" rdf:type="&ex;Music">

(接頭辞ex:との対応を分かりやすくするため、http://example.com/ex/を実体参照&ex;で表しています。rdf:type="http://example.com/ex/Music"と書くのと同じです)

[N3] プロパティ属性からのリテラルノードの生成

それ以外のpropertyAttrがある場合は、属性名をプロパティとし、属性値を目的語とした文をモデルに加えます。

(例) <rdf:Description rdf:about="urn:isbn:4-8399-0454-5" dc:creator="KANZAKI, Masahide">

目的語はリテラルなので、グラフでは四角で表現されていることに注意。

<s.URI> --- <property.URI> ---> [property.value]

[N4] プロパティ要素からのモデル生成

ノード要素の子要素(プロパティ要素)を、次節の規則によって順次処理します。

[N5] rdf:bagID属性による文の具体化

特別なケースとして、rdf:bagID属性がある時は、文全体が具体化(reification)されます。これについては、とりあえず詳細は割愛します。

プロパティ要素の生成規則

ノード要素の内容となるpropertyEltList(プロパティ要素リスト)は、アークを示すプロパティ要素の0回以上の繰り返しで構成されます。親ノードの主語に対する述語となるのは、これらプロパティ要素の要素型名(QName)です。目的語を含むモデルは、以下の生成規則によって与えられます(以下の例で、外側のrdf:Description要素は、プロパティの主語を与えるための親ノード要素です)。

[P1] リソースプロパティ要素

内容に前節のノード要素を含むものは、そのノードが目的語となります。基本的なストライピングの構文です。

(例)

<rdf:Description rdf:about="urn:pin:MK705">
 <ex:homePage>
  <rdf:Description rdf:about="http://kanzaki.com">
  </rdf:Description>
 </ex:homePage>
</rdf:Description>

この例では、ex:homePageが述語になっています。ここからは、親ノード要素のs.URIを主語とし、子ノード要素のs.URIを目的語とした、次のグラフが導かれます。

<parent.s.URI> --- <ex:propElt.URI> ---> <node.s.URI>

ノード要素にプロパティ属性があったり、子要素にプロパティ要素があれば、前節の規則に従い、さらにグラフは伸びていきます。

※ここでもしプロパティ要素ex:homePagerdf:ID属性が与えられると、ノード要素のrdf:bagID属性([N5])と同様、文全体が具体化されます。とりあえず、詳細は略します。

[P2] リテラルプロパティ要素

要素内容がリテラル(文字列)であるプロパティ要素からは、その内容を目的語とし、[N3]と同様のリテラルノードが導かれます。

(例)

<rdf:Description rdf:about="urn:isbn:4-8399-0454-5">
 <dc:creator>KANZAKI, Masahide</dc:creator>
</rdf:Description>

<parent.s.URI> --- <propElt.URI> ---> [propElt.content]

[P3] リテラルパース型プロパティ要素

属性parseType="Literal"を持つプロパティ要素は、要素内容をリテラルとして扱い、RDFではそれ以上のパース対象としません。目的語に何らかの別のマークアップを含める場合などに使うことができます。

(例)

<rdf:Description rdf:about="urn:isbn:4-8399-0454-5">
 <dc:creator rdf:parseType="Literal">
  <h:ruby>
   <h:rb>神崎正英</h:rb><h:rt>かんざきまさひで</h:rt>
  </h:ruby>
 </dc:creator>
</rdf:Description>

dc:creator要素の内容は、タグも含めてそのまま文字列として扱われ、リテラルノードになります。アプリケーションは、このマークアップを利用した(ルビを振るなどの)独自の処理が可能です。

<parent.s.URI> --- <propElt.URI> ---> [propElt.content.literal]

〔補足〕

ここで、parseType="Literal"属性を指定しなかった場合、内容はノード要素と解釈され、[N1]からこのノードはh:rubyという「型」を持ち、さらにその内容であるh:rth:rb要素は[P2]リテラルプロパティ要素として扱われ、結果的に次のような全く異なるモデルが生成されてしまいます。

空白ノードからh:rb, h:rtのリテラルノードと、rdf:typeのh:rubyノードへのアークが伸びる

〔以上補足〕

RDFではparseType属性の値としてはLiteralResourceCollectionの3つが定義されており、それ以外の値が出現した場合は、Literalと同じ扱いになります(OWLに合わせ、有限リストを表現するparseType="Collection"が追加されることになっています)。

[P4] リソースパース型プロパティ要素

属性parseType="Resource"を持つプロパティ要素は、要素内容をノード要素ではなくプロパティ要素として扱います。

(例)

<rdf:Description rdf:about="urn:isbn:4-8399-0454-5">
 <dc:creator rdf:parseType="Resource">
  <ex:name>KANZAKI, Masahide</ex:name>
  <ex:email>webmaster@kanzaki.com</ex:email>
 </dc:creator>
</rdf:Description>

プロパティ要素の中に“子プロパティ要素”が直接出現すると、(ノード要素がないため)アークが連続してしいます。そこで、ここに空白ノードを生成し、“子プロパティ要素”をそのプロパティとしてモデルがつくられます。

空白ノードが生成されて、そこからex:name、ex:mailのアークが伸びる

[P5] コレクションパース型プロパティ要素の目的語

通常、プロパティ要素の内容にはひとつのノード要素しか記述できません(アークの先にはひとつのノードしかない)が、属性parseType="Collection"を持つプロパティ要素は、内容に複数のノード要素を列挙できるようになります。rdf:Bagなどのコンテナモデルを使う場合と異なり、コレクションは列挙されるリストが有限であることを示します。

(例)

<rdf:Description rdf:about="urn:pin:MK705">
 <ex:homePage rdf:parseType="Collection">
  <ex:Site rdf:about="http://kanzaki.com"/>
  <ex:Site rdf:about="http://purl.org/net/kanzaki/"/>
 </ex:homePage>
</rdf:Description>

モデルはrdf:firstrdf:restというプロパティで、ひとつひとつのリストをつないでいくものです(2003-09-05の改訂で、少しシンプルになりました)。

ex:homePageの先に空白ノードが生成されて、そこからrdf:first、rdf:restのアークを使ってコレクションをひとつずつつないでいく。最後のrdf:restアークの目的語はrfd:nilとなる

このモデルは、OWLのクラス定義をowl:intersectionOfowl:unionOfなど集合によって行う時などに使われます。

[P6] 空プロパティ要素の目的語

プロパティ要素に対応するノードは、要素内容ではなく属性としてまとめて記述することもできます。

rdf:resource属性でURIを指定すると、[P1]で子ノード要素のrdf:about属性で目的語を指定したのと同じモデルを得られます。

(例)

<rdf:Description rdf:about="urn:pin:MK705">
 <ex:homePage rdf:resource="http://kanzaki.com"/>
</rdf:Description>

<parent.s.URI> --- <ex:propElt.URI> ---> <resourceAttr.URI>

[P7] 空プロパティ要素のプロパティ属性

さらに、空プロパティ要素で[N3]と同様のプロパティ属性を指定すると、この目的語についてのリテラル型プロパティまでを一度に記述することができます。

(例)

<rdf:Description rdf:about="urn:pin:MK705">
 <ex:homePage rdf:resource="http://kanzaki.com"
              dc:title="The Web KANZAKI"/>
</rdf:Description>

親要素(主語)ノードに別のプロパティを加えるのではなく、rdf:resource属性で示した目的語について、新たなモデルを追加することに注意してください。

<parent.s.URI> -- <ex:propElt.URI> --> <resourceAttr.URI> -- <ex:propAttr.URI> --> [propAttr.value]

rdf:resource属性がない場合は、空白ノードが生成され、[P4]と同様のモデルになります(P4の場合、rdf:resourcerdf:parseType="Resource"を同時に指定できないので、必然的に空白ノードとなります)。ただし、P4ではリソースノードも生成できるのに対し、このプロパティ属性で生成できるのはリテラルノードのみです。

生成規則を利用したXML構文の短縮例

ここまでとりあげた生成規則を利用して、[例1]のXMLをどんな具合に簡略化していくのかを見てみましょう。6〜9行目は、[P1]のリソースプロパティ要素の構文になっています。

(例)

 6:     <ex:homePage>
 7:      <rdf:Description rdf:about="http://kanzaki.com">
 8:      </rdf:Description>
 9:     </ex:homePage>

これが示すモデルは、[P6]の空プロパティ要素でも表現できますから

(例) <ex:homePage rdf:resource="http://kanzaki.com"/>

と1行にまとまります。3行目からのdc:creator要素もリソースプロパティ要素ですが、子ノード要素(4行目)はさらにその中に孫プロパティ要素を持つという構文です。

(例)

 3:   <dc:creator>
 4:    <rdf:Description>
 5:     <ex:name>KANZAKI, Masahide</ex:name>
        ...
10:    </rdf:Description>
11:   </dc:creator>

これは、[P4]parseType="Resource"を用いると、dc:creator要素の内容に、直接プロパティ要素を記述することが可能です。先ほどのex:homePage要素と合わせて

(例)

<dc:creator rdf:parseType="Resource">
 <ex:name>KANZAKI, Masahide</ex:name>
 <ex:homePage rdf:resource="http://kanzaki.com"/>
</dc:creator>

と短縮でき、[例2]が得られます。

〔補足〕

ここで、さらに[P7]のプロパティ属性を利用して次のようにまとめられそうな気もします。

(例) <dc:creator ex:name="KANZAKI, Masahide" ex:homePage="http://kanzaki.com"/>

しかしこの場合、http://kanzaki.comはリソースを指すURIではなくリテラル文字列として扱われるので、異なるモデルとなってしまい、この簡略化は成立しません(ex:nameのようなリテラルプロパティについては、この方法でまとめることが可能です)。

〔以上補足〕

参照文献

[RDFMS]
Ora Lassila, et al., Resource Description Framework (RDF) Model and Syntax Specification, , W3C Recommendation
<http://www.w3.org/TR/REC-rdf-syntax>
[STRIPE]
Dan Brickley, RDF: Understanding the Striped RDF/XML Syntax, , v 1.29
<http://www.w3.org/2001/10/stripes/>
[RDF/XML]
Dave Beckett, RDF/XML Syntax Specification (Revised), , W3C Working Draft
<http://www.w3.org/TR/rdf-syntax-grammar/>