WWW Watch

OPML の仕様に関するまとめ

OPML の仕様などについて調べてみたので書いてみることにしました。サンプルソースとして OPML 2.0 で RSS をまとめた文書を掲載しています。

OPML先日、livedoor Reader 内、「おすすめフィード」 のコーナーに、当サイトも参加させていただいている AMN パートナーブログの OPML が掲載されたそうです。

で、告知だけだとあれなので、今回は OPML(Outline Processor Markup Language) について書いてみることに。というのも、OPML 自体はRSS リーダー等のサービス間でのデータ移動 (インポート、エクスポート) などを始め、ツールが生成したり、他の人が公開しているものを利用する側としてはかなり前から慣れ親しんでいるフォーマットですが、自分で書いて公開したことってほとんどなくて、その仕様なんかも詳しく調べたことなかかったことに気付き、いい機会なのでちょっと調べてみたというわけです。

OPML は新しいフォーマットではないので今さら感もありますが、いまいち情報が少ないので現時点でのまとめみたいになればいいなと思います。

まずは、今回参考にしたページを仕様関係から。

次に補助的な情報。

Opml.org の Spec ページを見ると 2007年の 11月付けで OPML 2.0 が最新の仕様として公開されていてそこで更新は止まっていますので、最新のバージョンとしては、OPML 2.0 ってことになると思います。上記のとおり、XML Schema も公開されています。

OPML 2.0 の Specification を見ると、「Subscription lists」 として、RSS をまとめて公開するための属性、及び属性値のフォーマットに関しての記述が追加されており、ここで outline 要素に対して xmlUrl 属性、htmlUrl 属性といった、現在多くの RSS リーダー等が対応している属性名が明確に定義されています。逆にいえば、OPML 1.0 ではこの辺の属性は定義されておらず、OPML 1.0 DTD では、

<!ELEMENT body (outline)+ >
<!ELEMENT outline (outline)* >
 
<!ENTITY % OtherAttributes  " "       >
<!ATTLIST outline
text CDATA #IMPLIED
type CDATA #IMPLIED
isComment (true|false) false
isBreakpoint (true|false) false
%OtherAttributes; >
<!--
text is the string of characters that's displayed when the outline is being browsed or edited. 
type is a string, it says how the other attributes of the <outline> are interpreted.
isComment indicates whether the outline is commented or not.
By convention if an outline is commented, all subordinate outlines are considered to be commented as well.
isBreakpoint indicates whether a breakpoint is set on this outline.This attribute is mainly necessary for outlines used to edit scripts that execute.
 
You can add whatever other attributes on the outline element you want.
-->

text、type、isComment、isBreakpoint の各属性のみ定義済みであとは自由に好きな属性を付け加えていいよとなっています。しかしその後、RSS のリストを公開するという用途での OPML 利用が広まったため、そこで使用されていた xmlUrl 属性、htmlUrl 属性などが明記されるようになったようです。

ということで、実際に OPML 2.0 を使用して フィードのリストをまとめて公開するための文書を作ってみましょう。OPML の仕様は簡単。まずはサンプルソースを下記に。

<?xml version="1.0" encoding="utf-8"?>
<opml version="2.0">
 <head>
  <title>mySubscriptions.opml</title>
  <dateCreated>Sat, 29 Mar 2008 12:11:52 +0900</dateCreated>
  <dateModified>Sun, 30 Mar 2008 21:42:48 +0900</dateModified>
  <ownerName>WWW WATCH</ownerName>
  <ownerEmail>example@example.com</ownerEmail>
  <ownerId>http://hyper-text.org/</ownerId>
 </head>
 <body>
  <outline text="My Blogs RSS Feed" title="My Blogs RSS Feed">
   <outline text="My Blog 1" title="My Blog 1" description="My sample blog 1" type="rss" language="ja" xmlUrl="http://example.com/rss/sample_1.xml" htmlUrl="http://example.com/sample1/" />
   <outline text="My Blog 2" title="My Blog 2" description="My sample blog 2" type="rss" language="ja" xmlUrl="http://example.com/rss/sample_2.xml" htmlUrl="http://example.com/sample2/" />
   <outline text="My Blog 3" title="My Blog 3" description="My sample blog 3" type="rss" language="ja" xmlUrl="http://example.com/rss/sample_3.xml" htmlUrl="http://example.com/sample3/" />
  </outline>
  <outline text="My Favorite Blogs RSS Feed" title="My Favorite Blogs RSS Feed">
   <outline text="My Favorite Blog 1" title="My Favorite Blog 1" description="My Favorite blog 1" type="rss" language="ja" xmlUrl="http://example.com/rss/favorite_1.xml" htmlUrl="http://example.com/favorite1/" />
   <outline text="My Favorite Blog 2" title="My Favorite Blog 2" description="My Favorite blog 2" type="rss" language="ja" xmlUrl="http://example.com/rss/favorite_2.xml" htmlUrl="http://example.com/favorite2/" />
   <outline text="My Favorite Blog 3" title="My Favorite Blog 3" description="My Favorite blog 3" type="rss" language="en" xmlUrl="http://example.com/rss/favorite_3.xml" htmlUrl="http://example.com/favorite3/" />
  </outline>
 </body>
</opml>

ルート要素は opml 要素になります。OPML 2.0 XML Schema を見ると、

<xs:complexType name="opmlType">
 <xs:annotation>
  <xs:documentation>version - is a number defining the edition of OPML used</xs:documentation>
 </xs:annotation>
 <xs:sequence>
  <xs:element name="head" type="headType" minOccurs="1" maxOccurs="1"/>
  <xs:element name="body" type="bodyType" minOccurs="1" maxOccurs="1"/>
 </xs:sequence>
 <xs:attribute name="version" type="versionType" use="required"/>
</xs:complexType>

となっていますので、opml 要素には version 属性が必須。また、opml 要素内には、head 要素、及び body 要素が 1つだけ必須になります。version は OPML 2.0 で書くなら、「version="2.0"」 と記述します。

次に head 要素を見てみましょう。

<xs:complexType name="headType">
 <xs:annotation>
  <xs:documentation>headType - contains zero or more of the optional elements defined below</xs:documentation>
  <xs:documentation>title - title or name of the document</xs:documentation>
  <xs:documentation>dateCreated - a date-time indicating when the document is created; conforms to RFC 822 (http://asg.web.cmu.edu/rfc/rfc822.html); see the Simple Types section for more information</xs:documentation>
  <xs:documentation>dateModified - a date-time indicating when the document has last modified; conforms to RFC 822 (http://asg.web.cmu.edu/rfc/rfc822.html); see the Simple Types section for more information</xs:documentation>
  <xs:documentation>ownerName - the owner of the document</xs:documentation>
  <xs:documentation>ownerEmail - the email address of the owner of the document; see the Simple Types section for more information</xs:documentation>
  <xs:documentation>ownerId - an http address of a web page that contains a form that allows a human reader to communicate with the author of the document via email or other means</xs:documentation>
  …(中略)…
 </xs:annotation>
 
 <xs:sequence>
   <xs:element name="title" type="xs:string" minOccurs="0" maxOccurs="1"/>
   <xs:element name="dateCreated" type="rfc822Type" minOccurs="0" maxOccurs="1"/>
   <xs:element name="dateModifed" type="rfc822Type" minOccurs="0" maxOccurs="1"/>
   <xs:element name="ownerName" type="xs:string" minOccurs="0" maxOccurs="1"/>
   <xs:element name="ownerEmail" type="tEmailAddress" minOccurs="0" maxOccurs="1"/>
   <xs:element name="ownerId" type="xs:anyURI" minOccurs="0" maxOccurs="1"/>
  …(中略)…
 </xs:sequence>
</xs:complexType>

head 要素内には、0個以上の要素が必要となっていますので、空でも問題ないのですが、タイトルとか制作者情報はここに記述します。要素名のままなので難しくはないと思いますが、dateCreated、dateModified 要素は、RFC 822 に従い記述する必要があるとなっています。RFC 822 はすでに破棄され RFC 2822 に取って代わられているのでちょっとここはイケてないんですが。

次に body 要素。

<xs:complexType name="bodyType">
 <xs:annotation>
  <xs:documentation>bodyType - contains one or more outline elements</xs:documentation>
  <xs:documentation>outline - the contents to be displayed; may contain encoded HMTL markup; see outlineType</xs:documentation>
 </xs:annotation>
 <xs:sequence>
  <xs:element name="outline" type="outlineWithTypeType" minOccurs="1" maxOccurs="unbounded"/>
 </xs:sequence>
</xs:complexType>

1つ以上の outline 要素が必須。で、outline 要素はというと、

<xs:complexType name="outlineType" mixed="true">
 <xs:annotation>
  <xs:documentation>text - the content to be displayed to users</xs:documentation>
  <xs:documentation>isComment - indicates whether the outline is commented or not; by convention if an outline is commented, then all subordinate outlines are considered commented</xs:documentation>
  <xs:documentation>isBreakpoint - indicates whether a breakpoint is set on this outline</xs:documentation>
  <xs:documentation>created - generation date-time of the outline node</xs:documentation>
  <xs:documentation>category - comma-separated, slash-delimited sets of strings</xs:documentation>
  <xs:documentation>description - the top-level description element from a feed</xs:documentation>
  <xs:documentation>url - an http address to display in a browser or a pointer an OPML file</xs:documentation>
  <xs:documentation>htmlUrl - the top-level link element from a feed; that is a feed attribute that tells a reader where the HTML version of the feed exists</xs:documentation>
  <xs:documentation>xmlUrl - the http address of the feed in XML</xs:documentation>
  <xs:documentation>title - the top-level title element from a feed</xs:documentation>
  <xs:documentation>version - the type of feed (e.g. RSS2, RSS1, etc.)</xs:documentation>
  <xs:documentation>language - the top-level language element from a feed</xs:documentation>
 </xs:annotation>
 
 <xs:attribute name="text" type="xs:string" use="required"/>
 <xs:attribute name="isComment" type="xs:boolean" use="optional" default="false"/>
 <xs:attribute name="isBreakpoint" type="xs:boolean" use="optional" default="false"/>
 <xs:attribute name="created" type="rfc822Type" use="optional"/>
 <xs:attribute name="category" type="xs:string" use="optional"/>
 <xs:attribute name="description" type="xs:string" use="optional"/>
 <xs:attribute name="url" type="xs:anyURI" use="optional"/>
 <xs:attribute name="htmlUrl" type="xs:anyURI" use="optional"/>
 <xs:attribute name="xmlUrl" type="xs:anyURI" use="optional"/>
 <xs:attribute name="title" type="xs:string" use="optional"/>
 <xs:attribute name="version" type="xs:string" use="optional"/>
 <xs:attribute name="language" type="union.languageType" use="optional"/>
</xs:complexType>

それから、上記に関連して type 属性の定義も、

<xs:attributeGroup name="typeAttribute">
  <xs:annotation>
   <xs:documentation>type - indicator of how the attributes on the outline element are to be interpreted</xs:documentation>
  </xs:annotation>
  <xs:attribute name="type" type="union.typeType" use="optional" default="text"/>
</xs:attributeGroup>

ながい… ということで必須属性は text 属性。0個以上のオプション属性、テキストデータを持つことができ、0個以上の outline 要素を子要素として持つこともできます。(上記引用部分の下にて定義されてます。)

その他、RSS のまとめファイルとして OPML を使用する場合に outline 要素で使うことになるのが、

  • text 属性(必須属性)
  • type 属性
  • title 属性
  • xmlUrl 属性
  • htmlUrl 属性

あたりの属性。type 属性に 「rss」 とか 「atom」 記述、title 属性にフィードのタイトル、text 属性は必須なので title 属性と同じ値を。xmlUrl 属性にフィードの URI、htmlUrl 属性にサイトの URI を入れてあげれば OK って感じですね。そうすると上記のサンプル OPML みたいになります。

ちなみに、text 属性が必須になったのは OPML 2.0 からですので、OPML のバージョンを 「1.0」 で書くなら text 属性はいりません(何でもいいから属性が 1つ以上あれば OK)。それを踏まえて上記のサンプルを OPML 1.0 にした上で、要素や属性も削ってシンプルにするとこんな感じになります。

<?xml version="1.0" encoding="utf-8"?>
<opml version="1.0">
 <head>
  <title>mySubscriptions.opml</title>
  <dateCreated>Sat, 29 Mar 2008 12:11:52 +0900</dateCreated>
  <ownerName>WWW WATCH</ownerName>
 </head>
 <body>
  <outline title="My Blogs RSS Feed">
   <outline title="My Blog 1" type="rss" xmlUrl="http://example.com/rss/sample_1.xml" htmlUrl="http://example.com/sample1/" />
   <outline title="My Blog 2" type="rss" xmlUrl="http://example.com/rss/sample_2.xml" htmlUrl="http://example.com/sample2/" />
   <outline title="My Blog 3" type="rss" xmlUrl="http://example.com/rss/sample_3.xml" htmlUrl="http://example.com/sample3/" />
  </outline>
  <outline title="My Favorite Blogs RSS Feed">
   <outline title="My Favorite Blog 1" type="rss" xmlUrl="http://example.com/rss/favorite_1.xml" htmlUrl="http://example.com/favorite1/" />
   <outline title="My Favorite Blog 2" type="rss" xmlUrl="http://example.com/rss/favorite_2.xml" htmlUrl="http://example.com/favorite2/" />
   <outline title="My Favorite Blog 3" type="rss" xmlUrl="http://example.com/rss/favorite_3.xml" htmlUrl="http://example.com/favorite3/" />
  </outline>
 </body>
</opml>

で、最後に実際に OPML 2.0 で作ったファイルとしてウチの会社の社員ブログのフィードをまとめた OPML ファイルを上げておきます。

Recent Entry

全ての記事一覧を見る

Hot Entry

逆引きおすすめエントリー