Home of: [工房 "藤車"] > [SASAX-RSS]

実装メモ

本ドキュメントの目的は、 SASAX-RSS 実装の詳細を説明することにあります。

このドキュメントは、 SASAX フレームワーク上で固有の XML 文書パーサを記述する際の、 一助になるでしょう。

注意: 本ドキュメントで提示するソースコードは、 配布物との厳密な一致よりも、 説明の簡便さを優先しました。

チュートリアルでの記述と配布物の違いに、 混乱しないことを願います。

クラス名

本チュートリアルでは、 クラスは全てクラス名のみで表記されています。 完全な名称は以下の通りです。

SAX フレームワークのクラス

表記完全名
Attributes org.xml.sax.Attributes
SAXException org.xml.sax.SAXException

SASAX フレームワークのクラス

これらのクラスの詳細に関しては、 ドキュメント配布版ないし WEB 版の JavaDoc を参照してください。

表記完全名
AbstractElement jp.ne.dti.lares.foozy.sasax.AbstractElement
CompositeElement jp.ne.dti.lares.foozy.sasax.CompositeElement
DateTimeElement jp.ne.dti.lares.foozy.sasax.DateTimeElement
Element jp.ne.dti.lares.foozy.sasax.Element
ElementDrivenHandler jp.ne.dti.lares.foozy.sasax.ElementDrivenHandler
Notification jp.ne.dti.lares.foozy.sasax.Notification
ParseContext jp.ne.dti.lares.foozy.sasax.ParseContext

SASAX-RSS パーサのクラス

表記完全名
ChannelElement jp.ne.dti.lares.foozy.sasax.rss.ChannelElement
ItemElement jp.ne.dti.lares.foozy.sasax.rss.ItemElement
RSSRootElement jp.ne.dti.lares.foozy.sasax.rss.RSSRootElement

SASAX-RSS GUI のクラス

表記完全名
Channel jp.ne.dti.lares.foozy.sasax.rss.Channel
ChannelNotification jp.ne.dti.lares.foozy.sasax.rss.ChannelNotification
Item jp.ne.dti.lares.foozy.sasax.rss.Item
ItemNotification jp.ne.dti.lares.foozy.sasax.rss.ItemNotification

SASAX-RSS パーサ

SASAX のチュートリアルを既読で RSS 仕様を理解しているのであれば、 SASAX-RSS のパーサ部を読んで理解するのは十分容易です。

SASAX チュートリアルで記述されていない幾つかの事柄のうちの一つに、 "ignore"/"ordered" 引数を持つ CompositeElement コンストラクタのことがあります。

このコンストラクタは SASAX 1.2 から導入され、 以下の意味を持ちます。

ignore
この引数は、 未知(= 未登録)の要素を受け入れるか否かを表します。 RSS 仕様書によれば、 "channel"/"image"/"item"/"textinput" 要素の直下要素としてのみ未知の要素が許されています。
ordered

この引数は、 文書中の要素の出現順が登録順と一致している必要があるか否かを表します。 RSS 仕様書によれば、 要素順は制限されていません。

XML 文書からのデシリアライズ

SASAX-RSS パーサからの分離

SASAX-RSS パーサは、 指定された XML 文書が RSS 文書として適切か否かの検証しかしません。

RSS 文書から情報 (例: "channel" の詳細, "item" の一覧等々)を取得するためには、 何らかのことをする必要があり、 ほとんど全ての場合において「何らかのこと」とは情報コンテナの設定です。

情報コンテナの設定は XML 文書からの(情報コンテナ) オブジェクトのデシリアライズの一種と言える物で、 コンテナ定義固有のものです。 そのため、SASAX-RSS の GUI 部の持っているデシリアライズ実装は、 SASAX-RSS パーサとは分離されています。

SASAX を利用する際の解析結果取得には幾つかの方法があります。

解析後に値を取得する:
これは最も容易な方法ですが 複雑な文書(例: 反復要素の値一覧を取得する)には適していません。
notifyDetermined() メソッドのオーバライド:
AbstractElement 派生クラスにおいてこの方法を使用する事で、 値確定後に即座に解析結果を取得することが出来ますが、 Element 実装クラスと結果処理ロジックの双方の再利用性が低下します。
Notification として開始/終了イベントを受け取る:
SASAX では、 デシリアライズロジックを Notification 実装とすることで、 XML 文書解析ロジックと、 個々のアプリケーション固有のデシリアライズロジックを、 それぞれ分離することが出来ます。

そのため、SASAX-RSS では最後の手法を選択しました。

デシリアライズ実装

例えば、 "channel" RSS 要素のデシリアライズコードは以下のようになります。 これは Notification 実装クラスである ChannelNotification のものです。

以下の例では "channel_" は Channel 型のメンバフィールドです。 Channel は RSS "channel" 情報を格納するためのコンテナです。


public void elementStarted(Element element,
                           ParseContext context,
                           Attributes attributes)
    throws SAXException //
{
    // "rdf:about" 属性の取得
    String about =
    attributes.getValue("http://purl.org/rss/1.0/", 
                        "about");
    channel_.setValue("rdf:about", // 値の名前
                      about);
}

"channel" 要素開始における処理

ハイライト部分は XML 文書由来の情報を保持していることを表しています。


public void elementEnded(Element element,
                         ParseContext context)
    throws SAXException //
{
    ChannelElement channel = (ChannelElement)element;
    // "rss:title" 値の取得
    channel_.setValue("title", 
                      channel.title.getString(true));
    // "rss:link" 値の取得
    channel_.setValue("link",
                      channel.link.getString(true));
    // "rss:description" 値の取得
    channel_.setValue("description",
                      channel.description.getString(true));
}

"channel" 要素終了における処理

要素属性値を必要とするデシリアライズ処理は elementStarted() に、 下位要素の確定が必要とされる他のデシリアライズ処理は elementEnded() に記述されます。 難しくないですよね?

解析時には、 デシリアライズを行うための Notification を、 対応する要素に対して以下のように登録する必要があります。


// 情報コンテナの生成
Channel channel = new Channel();
// RSS 文書解析用 Element の生成
RSSRootElement root = new RSSRootElement(null);
// "channel" 要素への Notifiation の登録
root.channel.addNotification(new ChannelNotification(channel));

          :

ElementDrivenHandler handler = new ElementDrivenHandler(root);
handler.parse(reader); // RSS XML 文書の解析
// この時点で XML 文書から Channel がデシリアライズされる

デシリアライズ処理

拡張

本節では、 RSS "item" 配下へ "Dublin Core" の "date" を追加するための実装を示すことで、 拡張要素の追加とそこからの値取得の方法に関して説明します。

SASAX-RSS GUI ソースファイルでは、 "Dublin Core" の "date" 向け固有の実装部分を ">>>> DC:DATE" および "<<<< DC:DATE" で囲んであります。

このような箇所は4箇所しかありません。 そのうちの一つは共有のための文字列シンボル定義であり、 もう一つは表示のためのものです。 それ以外の二つが純粋にデシリアライズのためのコードで、 "要素の登録" と "要素からのデシリアライズ" です。

要素の登録

"Dublin Core" の "date" には DateTimeElement が利用可能で、 要素登録コードは以下のようになります。


LooseDateTimeElement dcDate =
new LooseDateTimeElement(root.item,
                         "http://purl.org/dc/elements/1.1/",
                         "date",
                         null // GMT タイムゾーンの意
                         );
// dcDate 要素を "item" 配下に非必須要素として登録
root.item.addOptionalItem("dc:date", dcDate);

"Dublin Core" の "date" 要素

要素からのデシリアライズ

"item" 要素のための ItemNotification におけるデシリアライズコードは、 以下のようになります。


public void elementEnded(Element element,
                         ParseContext context)
    throws SAXException //
{
    ItemElement item = (ItemElement)element;

        :

    LooseDateTimeElement dcDate =
    (LooseDateTimeElement)(item.getComponent("dc:date"));
    item_.setValue("dc:date", dcDate.getDate(false));
}

"Dublin Core" の "date" 要素からのデシリアライズ

上記例での "item_" は、 Item 型のメンバフィールドです。 Item は RSS "item" の情報を格納するコンテナです。