レベル: 中級 Dethe Elza (delza@livingcode.org), Senior Technical Architect, Blast Radius David Mertz, Ph.D (mertz@gnosis.cx), Author, Gnosis Software, Inc.
2006年 4月 25日 コンピューティングにおける最もエレガントな概念の1つは、UNIX®のパイプ構造です。パイプを使用すると、あることをうまく処理できる小さなプログラムを再利用し、そのプログラムを接続して、あるプログラムからの出力を別のプログラムへの入力として送ることができます。あいにく、UNIXのパイプは、ほとんどが行指向なので、XML処理に簡単に応用することはできませんでした。この記事では、これを解決するために試されたいくつかの既存ツールをレビューします。
ストリームとは、パイプに関連する概念です。つまり、パイプの操作対象です。ストリームというアイデアは、使用可能なデータがすべて揃う前にプログラムが作業を開始できるようにしようというものです。このため、生成されるデータを生成と同時に処理したり、ネットワーク経由で受信するデータを受信した順に処理したり、または大きすぎてメモリーに入りきらないファイルを処理することができます。
(注: 以下のパラグラフでは、多数のツール、仕様、およびライブラリーについて述べます。これらへのリンクは、この記事の末尾の「参考文献」にあります。)
なぜパイプストリームなのか
パイプとストリームというメタファーは、UNIXでは非常にうまく機能していて、程度の差はありますが、他の多くのシステムにも適用できます。形式はさまざまですが、ほとんどのプログラミング言語とオペレーティング・システムで使用可能です。XMLの用例で、最も知られているパイプおよびストリーム処理はSAX Filtersです。この記事のほとんどの読者がご存じのとおり、SAXとはSimple API for XMLのことです。SAXは、ストリーム・ベースのAPIであり、XMLを解析して、解析中に重要なイベント(要素のオープンやクローズなど)が発生した場合はイベント・ハンドラーを呼び出します。SAX処理は状態を維持したり、(DOMのように)巨大なデータ構造体を構築したりする必要がないため、(メモリーに入りきらない)大きなデータ・セットを操作するXMLタスク、非常に高速でなければならないXMLタスク、または(XMLデータの一部だけを選択し、残りは無視されるような)疎なXMLタスクで一般的に使用されます。
プログラミング言語レベル(例えばJavaTM InputStreamReaderクラスまたはSAX Filters)でパイプとフィルターを使用する際の問題は、非常に低レベルでの作業になるため、煩雑で、エラーが起きやすく、繰り返しの多いコードになってしまうことです。コードの抽象度を上げつつ、多種多様なXML処理タスクの柔軟性を維持する方法を見つけるのが、今回多数のライブラリーとツールをレビューする目的です。また、多くの場合、多段処理(パイプライン)用のXMLツールを複数接続することにより、XMLを何度もパースしなおすことになるため、各段階から渡された処理済みのXMLをメモリーに置いておく方がいいでしょう。
しかし、まず、パイプストリーム・ライブラリーでどんな問題を解決できるか見てみましょう。この抽象的なXML操作方法を望むのは、それはそれでいいとして、では、いったいこれで何ができるのでしょうか。
XMLパイプラインの一般的な用途には、次のようなものがあります。
- XMLの読み取り/パース(ディスク、ネットワーク、CMSなどから)
- 非XMLからXMLへの変換(例えば、reStructured TextからXHTMLへの変換)
- 検証(DTD、XSchema、RelaxNG、またはSchematronを使用しているかどうか)
- XML断片の集約(例えば、XIncludeまたはDITA Mapsを通じて)
- 変換(おそらくXSLTを使用して)
- テンプレートへの値の流し込み(プレースホルダー値を実際のコンテンツに置換)
- 表示または印刷のためのフォーマット設定(CSSまたはXSL-FOを用いて)
- XMLのシリアライズ/書き戻し(ディスク、ネットワーク、CMSなどへ)
- すべてを宣言構文としてまとめる(一般にXMLも)
パイプラインにはこれらの用途の一部または全部を含めることができ、繰り返しや変更も可能です。他のカスタム要素が含まれる場合もあります。しかし、これらがXML処理の中心的成分のようです。また、すでに述べたように、パイプラインは、各段階で再パースするのではなく、プロセスを通じてパース済みのXMLを保持します。
例えば、人とイベントを表す少量のマークアップからWebカレンダーを組み立てることができます。あるいは、逆に、数人のWebカレンダーをスキャンして、全員のスケジュールを集約して会議の日時を決めることもできます。この例ではカレンダーと人を使用しますが、このアイデアは、XMLで表現できるあらゆるもの(最近はかなり長いリスト)に関連します。
マイクロフォーマットの転用
例としてカレンダーを使用する理由の1つは、「マイクロフォーマット」と呼ばれるトレンドがあるからです。マイクロフォーマットは、ホイールなどを再発明しようとするのではなく、既存の仕様を既存のXML方言で表現しようとするものです。マイクロフォーマットが注目する最も一般的なXML方言はXHTMLです。クラスおよびリンク属性を使用してセマンティクスを追加し、どちらも人間が読める形式(Webページ)とマシンが読める形式(マシン固有のデータを属性に含める)にすることが目的です。マイクロフォーマットには、人と組織(vCard仕様に基づくhCard)、カレンダーとイベント(iCalendar仕様に基づくhCalendar)、アウトラインとリンク(XOXO)、タグとキーワード(rel-tag)、レビュー(hReview)、社会的ネットワーク(XFN)、コンテンツ・ライセンシング(rel-license)用などがあります。ここでは、この記事の目的から、hCalendarを中心に説明します。
リスト1は、hCalendarマイクロフォーマットの例です。
リスト1. hCalendarマイクロフォーマット
<div class="vevent">
<abbr class="dtstart" title="20060322T0830-0800">
March 22, 2006 - 08:30
</abbr> -
<abbr class="dtend" title="20060322T0900-0800">
09:00
</abbr> -
<span class="summary">
Dentist Appointment
</span> - at
<span class="location">
Office on Pacific Ave.
</span>
<div class="description">
Get permanent crown installed.
</div>
</div> |
この例は、hCalendarクリエイターで生成されました。Phil Dawesのサイトに、hCalendarとhCardを解析するpythonライブラリーがあり、hCalendarのページには、さらに多くのツールと実装があります。Greasemonkey拡張を使用しているFirefox®ユーザーのために、訪問したページからさまざまなマイクロフォーマットを抽出できるGreasemonkeyスクリプトもあります。Upcoming.orgとEventful.comのサイトでは、hCalendar形式のイベントとカレンダーを表示しています。確かに、マイクロフォーマットで動作する豊富なデータにアクセスできます。
パイプとストリームに戻って
XMLデータを作成または見つけた後、それを処理するパイプラインをどのようにして作成したらよいのでしょうか。作成方法はいくつかあり、それぞれ洗練度と複雑度が異なります。SAX Filtersは、他のいくつかのツールキットの基盤になったり、影響を与えた低レベルの配管です。XMLGAWKは、GNU AWK行型プログラミング言語を拡張してXMLの処理を可能にしたものであり、行指向ではなく要素指向になっています。XmlRpcFilteringPipeは、パイプストリームについてのLion Kimbroの見解であり、XML-RPCを使用してパイプラインを構築します。NetKernelTMは、パイプストリームのアイデアを取り入れて、すべてのノブを11にまとめた完全なツールキットのようです。Apache Cocoonは、「コンポーネント・パイプライン」という概念を中心に構築されています。概念としてはXMLパイプストリームに似ていますが、より複雑です。これらはいずれも優れた手法ですが、(筆者にとって)パワーと単純さのバランスが取れた2つのプロジェクトを取り上げ、その後、2つの有望な開発について説明したいと思います。
まず、Sean McGrathのXPipeがあります。SeanはPyxie(現在はPixie2)も開発しました。Pyxieは、標準のUNIXのパイプとフィルターで処理できるように、XMLを行指向の言語に変換します。XPipeは、これとJavaコンポーネントの拡張セットを利用します。Seanの方向性は正しかったと思いますが、努力が立ち消えになったようです。サイトはしばらく更新されていません。Seanが電子メールで教えてくれたところによると、Seanの会社は商用版の開発を続けているため、オープン・ソース版に割く時間がないそうなのですが、時間ができたら、動作を大幅に変えるつもりだそうです。Seanのアプローチはよかったのですが、基本的なコンセプトを守る方が簡単ではないかと思います。
筆者が今まで見た中での最強選手は、Norm WalshのSXPipe(Simple XML Pipeline)です。SXPipeには、この記事の冒頭で挙げた基本的なXML処理タスクのリストのほぼすべてを網羅する段階があり(これは偶然ではなく、筆者が挙げたリストはSXPipeの機能に基づいています)、詳しく仕様が定められているため、XMLを簡単に書くことができます。ただし、注意点がいくつかあります。デフォルトではJava 1.5が必要ですが、OS XではJava 1.5は開発者向けプレビューしか入手できず、段階そのものがかなり重いJavaコンポーネントであるため、システムの拡張があまり容易ではありません。しかし、SXPipeのメリットに比べると比較的小さな問題です。単純な構文と処理モデルはさておき、SXPipeはシンプルで(わずか5つの要素)、標準準拠です(XPath 1.0、XML名前空間、XML Base、XSL Transformationを使用し、これらの仕様を適切なコンテキストで(例外もあります)使用しています)。また、この言語はW3Cノート(Normも共同編集者の一人です)「XMLパイプライン定義言語」よりはるかに単純でありながら、以前の製品が持つ基本的なパワーと柔軟性を失っていません。リスト2に、サンプルのSXPipeドキュメントを示します。
リスト2. SXPipeドキュメント
<pipeline xmlns="http://sxpipe.dev.java.net/xmlns/sxpipe/">
<stage process="Read" input="dw-article.xml"/>
<stage process="Validate" schema="dw-article-5.0.xsd"/>
<stage process="Transform" stylesheet="dw-article-5.0.xsl"/>
<stage process="Write" output="dw-article.html"/>
</pipeline> |
かなりシンプルで、きれいです。筆者の理想の世界では、これを、Pythonを使用して拡張することができます。そうすれば、例えば、パイプラインの一部としてRestructured TextをXMLに処理する段階を容易に追加したり、Cheetahテンプレートを適用したりすることができます。PythonでのSXPipeの実装はそれほど難しくはないでしょうが、移植性を持たせるのが困難です。Pythonには、デフォルトではXSLまたはXML検証ライブラリーが同梱されていないからです。
パイプストリームの未来は明るいと言えます。一例を挙げると、非常に多くのツールが同じインスピレーションに基づいているという事実は、パイプストリームに対するニーズが本物であることを示しているように思えます。世界がいずれは(例えば)SXPipeに基づいて標準化されるとしても、それぞれ独自の道を進み続けるとしても、パイプとストリームのメタファーは生き続けるでしょう。筆者のお気に入りの言語であるPythonから見ると、PullDomが標準ライブラリーの一部になってからかなり経ち、次の2.5リリースでは、Fredrik Lundhの素晴らしいElementTreeライブラリーが加えられる予定です。筆者はElementTreeを使用してSXPipeを実装しようとしてみましたが、変換や検証、そして基本的なXPathサポートのためのツールがまだないようです。Martijn Faassenのlxmlライブラリーは、きわめてパワフルな、しかし使いにくいPythonのlibxml2とlibxsltをラップして、ElementTreeと同じようにシンプルなインターフェースと、XInclude、完全なXPath、XSLT、およびさまざまな形式のバリデーションを提示しています。このプロジェクトは安定しているので、PythonでSXPipeの優れた実装を作成するのが比較的簡単になりそうです。
まとめ
さて、マイクロフォーマット・コンテンツがあり、配管工事用のツールもあります。では、それで何ができるでしょうか。いくつか可能性を探ってみましょう。これは仮想上の実験なので、URLは例に過ぎず、実際にはどこにも存在しません。あなたは、Wanda(母)、Xathrus(父)、Yolanda(娘)、Zander(息子)の4人家族のNuclear家の一員だとします。家族はそれぞれ自分のWebページにhttp://example.com/calendar/[name]/[period]という形式のカレンダーを持っています。カレンダーの期間(period)は、年だけかもしれないし、年月、年月日かもしれません。あるいは、「tomorrow」や「next week」のような自然言語かもしれません。さて、あなたは全員のカレンダーを定期的にまとめて、Apple®のiCal®やMozilla®のSunbirdTMのようなプログラムにインポートしたいと考えています。WebからXSLT変換スタイルシートを取得して、hCalendarをiCalendarに変換し、cal-transform.xslという名前を付け、リスト3のソース・ドキュメント(source-calendar.xml)を使用します。
リスト3. source-calendar.xml
<calendar>
<xi:include href="http://example.com/calendar/Wanda/today"/>
<xi:include href="http://example.com/calendar/Xathrus/today"/>
<xi:include href="http://example.com/calendar/Yolanda/today"/>
<xi:include href="http://example.com/calendar/Zander/today"/>
</calendar>
|
次に、リスト4のパイプラインをソース・ドキュメントに適用します。
リスト4. ソース・ドキュメントへの追加
<pipeline xmlns="http://sxpipe.dev.java.net/xmlns/sxpipe/">
<stage process="Read" input="source-calendar.xml"/>
<stage process="XInclude"/>
<stage process="Transform" stylesheet="cal-transform.xsl"/>
<stage process="Write" systemId="family-calendar.ics"/>
</pipeline>
|
上記のすべてを実行して、パイプラインを実行すると、インポートが可能な単一のカレンダー・ファイルができあがります。別のユース・ケースを試してみましょう。マイクロフォーマットが普及すれば、銀行(預金取引明細とクレジット明細)、食料品店(デジタル形式の領収書)、そして図書館からも自分のデータをダウンロードできるはずです。ほとんどのデータについては、それが有効かどうか特に気になりませんが、銀行のデータはスキーマに照らして検証した方がよいでしょう。それぞれのデータ・ソースについてデータを変換し、すべてを同じ形式にした方が好都合です。そこで、想像力を働かせて(そして、今は、セキュリティー問題は無視してください。なんといっても、これはパイプドリームなのですから)、このばらばらなソースをリスト5のように1つのストリームに押し込みます。
リスト5. 単一のストリーム
<pipeline xmlns="http://sxpipe.dev.java.net/xmlns/sxpipe/">
<!-- Get my schedule for the day -->
<stage process="Read" input="http://myjob.com/myappointments"/>
<stage process="Transform" stylesheet="calendar-to-portal.xsl"/>
<stage process="Write" systemId="work.xml"/>
<!-- Do I have any books due back at the library? -->
<stage process="Read" input="http://muni-library.gov/books-due"/>
<stage process="Transform" stylesheet="library-to-portal.xsl"/>
<stage process="Write" systemId="library.xml"/>
<!-- Get latest transactions in my chequing account -->
<stage process="Read" input="http://mybank.com/chequeing-acct"/>
<stage process="Validate" schema="my-bank-acct.xsd"/>
<stage process="Transform" stylesheet="chequing-to-portal.xsl"/>
<stage process="Write" systemId="chequeing.xml"/>
<!-- Get latest transactions on my credit card -->
<stage process="Read" input="http://mybank.com/my-credit-acct"/>
<stage process="Validate" schema="my-creditcard.xsd"/>
<stage process="Transform" schema="creditcard-to-portal.xsl"/>
<stage process="Write" systemId="creditcard.xml"/>
<!-- Check the weather forecast -->
<stage process="Read" input="http://localweather.com"/>
<stage process="Transform" stylesheet="weather-to-portal.xsl"/>
<stage process="Write" systemId="weather.xml"/>
<!-- Create an XInclude document to glue it all together -->
<stage process="Document" label="accumulator">
<portal
xmlns:"http://www.example.com/portal">
<xi:include href="work.xml"/>
<xi:include href="library.xml"/>
<xi:include href="chequeing.xml"/>
<xi:include href="creditcard.xml"/>
<xi:include href="weather.xml"/>
</portal>
</stage>
<stage process="XInclude"/>
<!-- Convert it all to HTML -->
<stage process="Transform" stylesheet="portal-to-html.xsl"/>
<!-- Viola! We have our own personal portal on the world -->
<stage process="Write" systemId="my-daily-portal.html"/>
</pipeline>
|

 |
原子力時代
最後の例では、ちょっとした問題を何でもないとごまかしましたが、それは筆者がまだマイクロフォーマットとシンジケーションの交差について述べていないからです。現在のマイクロフォーマット・コンテンツの多くは、元々RSS形式でブログを読むために設計されたニュースフィード・アグリゲーターを通じて流すように設計されています(または、大急ぎでそのように改良されています)。また、前の例で示唆したように、単なるhCalendar以上のものがアグリゲーターに流されています。レビューとアウトライン、イベントと人のためのマイクロフォーマットはすでにありますが、金融取引、延滞図書、天気予報などのほか、まだ想像されてもいない用途のマイクロフォーマットもすぐに見られるようになるでしょう。
マイクロフォーマットと並んで、近い将来トレンドになりそうなのがAtomです。実際にはAtom syndication formatとAtom APIという2つの仕様です。Atomによるシンジケーションは、より古いRSSフォーマットによるシンジケーションとよく似ていますが、より明確に規定されています(また、IETF標準です)。しかし、これは次回の記事のテーマとします。次回は、マイクロフォーマットとAtomシンジケーションの交差について説明します。それまで、皆さんのパイプに水漏れがなく、ストリームがきれいでありますように。
参考文献 学ぶために
製品や技術を入手するために
-
Structured Blogging: WordpressおよびMovable Type用プラグインを入手して、ブログにマイクロフォーマットを追加してください。
-
Python microformat parser: さまざまなマイクロフォーマット用のPhil Dawesのパーサーを試してください。現在扱えるのは、hCardとhCalendarだけです。
-
ElementTree: Python 2.5にはFrederik LundhのPython向けXML処理用APIが含まれる予定ですが、個別にインストールすることもできます。
-
lxml: このライブラリーはElementTreeと同じシンプルなAPIを使用していますが、libxml2とlibxsltをベースとし、非常に高速であり、完全なXPath 1.0、XInclude、XSLT、XML Schema、RelaxNG検証などの追加機能を提供します。
著者について
 | 
|  | David Mertz氏は多くの分野で活躍しています。ソフトウェア開発や、それについて著述もしています。その他、学術政策理念について分野を問わず、関係する雑誌に記事も書いています。かなり以前には、超限集合論、ロジック、モデル理論などを研究していました。その後、労働組合組織者として活動していました。そして、David Mertz氏自身は人生の半ばにもまだ達していないと思っているので、これから何かほかの仕事をするかもしれません。 |
記事の評価
|