これまで何百もの XML 処理ツールが世の中に登場しましたが、アクションが行われる場所は常に Web ブラウザーであり、XML 開発者にとっては幸いなことに、そのアクションが遅くなることはなかったようです。私は過去数年、開発者が好む Firefox ブラウザーの XML 関連機能についてのシリーズ記事 (「参考文献」を参照) を書いてきましたが、そこでは Firefox 1.5 から 2.0 までを解説しました。Firefox は最近 3.0 にバージョン・アップされ、そこでは全体にわたって数え切れないほどの改善が行われており、XML 処理に関しても素晴らしい新たな進展が大量に見られます。こうした改善の多くは、Web 処理のためのコア・エンジンである Gecko がバージョン 1.8.1 から 1.9 にアップグレードされたことによるものです。
XML の領域には膨大な技術が積み重ねられていますが、すべては相変わらずパーサーから始まります。Firefox 3 では、基本的な XML 構文解析に 1 つの大きな改善が行われています。これまでの Mozilla ブラウザーでは XML 文書の構文解析は同期型であり、文書が完全にロードされるまで、その文書に対するすべての操作をブロックしていました。それとは対照的に、HTML の構文解析は常に非同期であり、文書の一部の構文解析が終わると、その部分を利用できるようになります。これをユーザーから見ると、ブラウザーがその Web ページの処理を完全に終わる前からそのページの構成が表示されるということです。一方 XML 文書の場合には、その文書が完全に構文解析されるまでユーザーには何も表示されませんでした。これは大規模な XML 文書を処理する際のネックとなり、使いにくさの問題につながっていました。
Firefox 3.0 では、XML のコンテンツ・モデルの作成は、HTML の場合とほとんど同じようにインクリメンタルに行われます。そのため、Web で実際に XML を使う上で大きな違いが生じます。これに関してはいくつかの例外があり、もっとも重要な例外は XSLT の処理がインクリメンタルではないことです。理論的には、制限付きの XPath サブセットを使って XSLT のサブセットをインクリメンタルに適用することができますが、それ自体が大変な作業である上、そうした処理は Firefox 3.0 の想定範囲を超えてしまいます。
Firefox 3.0 に関して私が期待していた改善項目の 1 つが xml:id のサポートです。xml:id をサポートするかどうかに関しては多少の議論がありましたが、パッチは入手可能であり、今後のリリースでサポートされる可能性が十分にあります。一般的な注意事項として、XML 文書で getElementById を使うために Firefox の JavaScript で提供されているのは内部 DTD サブセットのみとなっています (外部サブセットも xml:id も使うことはできません)。どうしても xml:id が必要な場合には、JavaScript で XPath を使って XML 名前空間での属性とローカル名 id に関するクエリーを実行します。
もう 1 つ期待していたけれども、実現されなかった主要な改善項目として、ブラウザーが外部の DTD サブセットをロードするようにユーザーが要求できる機能があります。これに関してもパッチは準備できているようですが、Q&A プロセスを終えるまでの十分な開発リソースが確保できず、Firefox 3.0 のリリースには含められなかったようです。
Firefox で XSLT を使おうとする人達にとって非常に嬉しいことは、EXSLT がサポートされるようになったことです (EXSLT は XSLT コミュニティーによって開発および認可され、また他の多くの XSLT プロセッサーでサポートされている一連の XSLT 拡張機能です)。Firefox 3.0 では大きなサブセットである EXSLT のサポートを追加しており、node-set 関数を始めとして、XSLT 1.0 による最も厳しい制約に対する有効な回避策が追加されています。EXSLT は複数のモジュールで構成されており、それぞれのモジュールがいくつかの拡張関数と拡張要素を定義しています。Firefox 3.0 では、そのモジュールの中でも選りすぐりのモジュールの選りすぐりの拡張機能を実装しています。それらは次のようなものです。
- Common: Firefox 3.0 は一連の基本的な汎用関数を実装しています。
exsl:node-setを利用すると結果ツリーのフラグメントをノード・セットに変えられるため、それらのノード・セットに XPath を適用することができます。exsl:object-typeはストリングやノード・セット、数値、あるいはブール値などオブジェクトの型をレポートするためのイントロスペクション・ツールです。
- Sets: Firefox 3.0 はノード・セットを扱うために便利な拡張機能をいくつか実装しています。
set:differenceは、2 つのノード・セット間の違いを抽出し、一方のノード・セットには含まれないがもう一方のノード・セットには含まれるノードからなるノード・セットを返します。set:distinctは、1 つのノード・セットの中で同じストリング値を持つノードが複数ある場合、そのストリング値を持つインスタンスを 1 つだけ残してあとは削除し、同じストリング値を持つノードが複数存在しないようなノード・セットにします。set:intersectionは、2 つのノード・セットのどちらにも含まれるノードを抽出し、ノード・セットとして返します。set:has-same-nodeは、2 つのノード・セットに共通のノードがあるかどうかを判断します (XPath の「=」演算子の場合と同様で、例えば 2 つのノード・セットが単に同じストリング値を持つ異なるノードを共有しているのではなく、実際に同じノードを共有しているかどうかを判断します)。set:leadingは、一方のノード・セットに含まれるノードのうち、もう一方のノード・セットの先頭ノードよりも文書内での順序が前に来るノードからなるノード・セットを返します。set:trailingは、一方のノード・セットに含まれるノードのうち、もう一方のノード・セットの先頭ノードよりも文書内での順序が後に来るノードからなるノード・セットを返します。
- Strings: Firefox 3.0 はストリングを扱うための便利な拡張機能をいくつか実装しています。
str:concatは、あるノード・セットの中の各ノードのストリング値を連結したストリングを返します (一定の順番で式を連結する組み込みの concat 関数と比較してみてください)。str:splitは、あるパターンを使って、ストリングを一連のサブストリングに分割します (この一連のサブストリングはこの関数の実行時に作成されるノード・セットとして表されます)。str:tokenizeは、1 文字のトークン・セットを使って、ストリングを一連のサブストリングに分割します (この一連のサブストリングはこの関数の実行時に作成されるノード・セットとして表されます)。
- Math: Firefox 3.0 は複数のノード・セットの内容の中から最小あるいは最大の数値を容易に取得できる関数をいくつか実装しています。
math:maxは指定されたノード・セットの内容の中で最大の数値を返します。math:minは指定されたノード・セットの内容の中で最小の数値を返します。math:highestは、ノードの内容に最大の数値を持つノード・セットを返します。math:lowestは、ノードの内容に最小の数値を持つノード・セットを返します。
- Regular expressions: Firefox 3.0 では、正規表現の威力を XSLT に適用することができます。
regexp:matchはストリングに対して正規表現パターンを突き合わせ、一致したサブストリングを含むノード・セットを実行時に作成して返します。regexp:testはストリングが正規表現のパターンと完全に一致するかどうかをチェックします。regexp:replaceは正規表現パターンと一致するサブストリングを置き換えます。
皆さんが作成する独自の変換処理の中で EXSLT を使い始められるように、私は Firefox 3.0 で実装されている関数を多数使用するサンプルを作成しました。ブラウザーでの XSLT の使い方として最適と思われるものは、ある程度構造化されたデータに対してレポートを作成することです。この場合ユーザーに対しては、XSLT 変換を適用するための処理命令を含む XML ファイルを提供します。こうした状況では、クロスブラウザーの互換性をあまり心配しなくてもすむように、必要なブラウザーのバージョンを指定することが多いものです。さらに、かなりの作業負荷をサーバーからユーザーのコンピューターに移します。リスト 1 (employees.xml) は従業員の情報ファイルであり、このファイルに対するレポートを Firefox 3.0 に表示します。
リスト 1. 従業員の情報ファイル (employees.xml)
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xml" href="employees.xsl"?>
<employees>
<department id="res">
<title>Research</title>
<info>http://example.com/ar-and-dee for more info</info>
<employee id="111">
<title>Coordinator</title>
<name>
<given>Rene</given>
<family>Descartes</family>
</name>
<location building="PAR1">France</location>
</employee>
<employee id="112">
<title>Project Manager</title>
<name>
<given>Abu Ja'far</given>
<family>Al Kwarizmi</family>
</name>
<location building="BAG2">Iraq</location>
</employee>
</department>
<department id="exec">
<title>Executive</title>
<info>Home of the head honchos</info>
<employee id="101">
<title>Chief Executive Officer</title>
<name>
<given>Genghis</given>
<family>Khan</family>
<honorific>The Great</honorific>
</name>
<location building="MON1">China</location>
</employee>
</department>
<department id="hr">
<title>Human Resources</title>
<info>We're happy to serve you at http://example.com/hr</info>
<employee id="102">
<title>Manager of Wellness</title>
<name>
<given>Ching-Yuen</given>
<family>Li</family>
</name>
<location building="SZE1">China</location>
</employee>
</department>
</employees>
|
先頭にある xml-stylesheet という処理命令に注目してください。この命令はブラウザーに対し、XSLT を使うように指示しています。リスト 2 (employees.xsl) はリスト 1 からレポートを生成するための変換です。
リスト 2. 従業員の情報ファイルからレポートを生成するための変換 (employees.xsl)
<?xml version="1.0" encoding="utf-8"?>
<!-- A -->
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:math="http://exslt.org/math"
xmlns:regex="http://exslt.org/regular-expressions"
xmlns:set="http://exslt.org/sets"
xmlns:str="http://exslt.org/strings"
xmlns="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="set math regex str">
<!-- Notice the namespace declarations for EXSLT.
Notice also exclude-result-prefixes, since you don't want those
namespace declarations in the result XHTML
-->
<!-- Use XML mode to approximate XHTML output
(notice the doc type declaration info) -->
<xsl:output method="xml" encoding="utf-8"
doctype-public="-//W3C//DTD XHTML 1.1//EN"
doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"/>
<xsl:template match="employees">
<!-- Put the presentation style into a separate file,
specified using a processing instruction in the output -->
<xsl:processing-instruction name="xml-stylesheet">
<xsl:text>type="text/css" href="employees.css"</xsl:text>
</xsl:processing-instruction>
<html xml:lang="en">
<head>
<title>Employee report</title>
</head>
<body>
<h1>Employee report</h1>
<table>
<xsl:apply-templates/>
</table>
<hr/>
<xsl:call-template name="stats"/>
</body>
</html>
</xsl:template>
<xsl:template name="stats">
<xsl:variable name="execs"
select="department[title='Executive']/employee"/>
<xsl:variable name="employees-in-china"
select="department/employee[location='China']"/>
<!-- Use set:has-same-node to check whether the two separate
XPath queries have any node sets in common -->
<xsl:if test="set:has-same-node($execs, $employees-in-china)">
<p>Note: At least one executive presently works in China</p>
</xsl:if>
<dl>
<dt>Countries where employees presently work</dt>
<dd>
<!-- Use set:distinct to eliminate duplicate country names
from the query result -->
<xsl:for-each select="set:distinct(department/employee/location)">
<xsl:value-of select="."/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</dd>
<dt>Newest employee</dt>
<!-- Use math:highest to determine the highest numerical value of employee ID -->
<dd><xsl:value-of select="math:highest(department/employee/@id)"/></dd>
</dl>
</xsl:template>
<xsl:template match="department">
<tr>
<td colspan="4">
<!-- Use regular expressions to sniff out URLs from unstructured content -->
<!-- [1] ensues that if multiple URLs are detected, only the first is used -->
<a href="{regex:match(info, 'http://[a-zA-Z0-9-_/\.]*', '')[1]}">
<xsl:value-of select="title"/>
</a>
</td>
</tr>
<xsl:apply-templates select="employee"/>
</xsl:template>
<xsl:template match="employee">
<tr>
<td>
<xsl:value-of select="name/given"/>
<xsl:text> </xsl:text>
<xsl:value-of select="name/family"/>
</td>
<td>
<!-- Use str:concat to construct a composite ID from ancestor -->
<!-- If, for example you added an id attribute to the root element,
the value would be appended for each employee -->
<xsl:value-of select="str:concat(ancestor-or-self::*/@id)"/>
</td>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<!-- Standard concat assembles a string from a fixed sequence of expressions -->
<xsl:value-of select="concat(location, '(', location/@building, ')')"/>
</td>
</tr>
</xsl:template>
</xsl:transform>
|
このコードでは、EXSLT を使っているところや、その他コメントがあると役立つところに、コメントをたくさん付けてあります。生成される出力は、主にこのパターンを示すために CSS スタイルシートを参照しています。リスト 3 (employees.css) はこの CSS です。
リスト 3. 従業員の情報ファイルからレポートを生成するための表示用スタイルシート (employees.css)
body { background-color: lightblue; }
td { padding-left: 1em; }
|
リスト 1 を Firefox 3.0 にロードすると、図 1 の内容が表示されます。
図 1. リスト 1 からリスト 3 までを使って生成されたレポートを Firefox 3.0 で表示する
Firefox 3.0 には、コアとなる構文解析機能の改善と EXSLT のサポートに加え、名前空間を持つ XML 文書を扱う際に標準に準拠するための修正がいくつか含まれています。DOMAttrModified イベントは名前空間の中の属性を適切に扱えるようになり、また JavaScript の DOM メソッドである getElementsByTagName() は、タグ名の中に名前空間の接頭辞を持つ要素を含むサブツリーに対しても適切に動作するようになりました。Firefox 3.0 では CSS や JavaScript に関して多くの修正が行われているため、XML 開発者の作業が楽になるはずです。
また、XML を利用した最高傑作として非常に人気のあるSVG (Scalable Vector Graphics) のユーザーのために、Firefox 3.0 はさらに便利なものを提供しています。Firefox 3.0 はパターンとマスクをサポートするようになり、その結果リッチな効果を実現するための選択肢が増えました (SVG 1.1 のフィルターはすべてサポートされています)。今やどんな古い Web ブラウザー・オブジェクトにも SVG 変換を適用することができるため、例えば IFRAME を 45 度回転するなど、通常は Canvas の機能を必要とする効果を実現することができます。Mozilla チームは SVG の DOM サポートを実現し、その作業の過程で大量のバグを解決しました。
XML は Web 上で期待されたような成功を収めていないと言う人がいるかもしれません。しかしブラウザーで XML を使って実現できることは既に多数あり、また Web ブラウザーが進化し続けているおかげで、より多くのことが毎年可能になっていきます。Firefox 3.0 は XML 処理に対するコア・パフォーマンスが改善され、また XSLT、DOM、そして SVG に関する機能強化が行われた重要なマイルストーンです。こうした新機能を試すことで何かが悪くなることはありません。クロスブラウザーの要件から、すべての機能を即座に使用することはできないとしても、Web アプリケーションでの最新技術の進化に合わせ、将来に対して備えることはできます。
| 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|---|---|---|
| Sample XML, XSL, CSS files | x-think41-samples.zip | 3KB | HTTP |
学ぶために
- Firefox 3 for developers を訪れ、Firefox 3.0 で更新された開発者向け機能を調べ、また主な改善点について学んでください。
- 重要な修正に関する詳細は、各修正項目のバグ・エントリーを見てください。
- 18333 - XML Content Sink should be incremental (XML コンテンツ・シンクはインクリメンタルでなければならない)
- 365801 - expose EXSLT functions to DOM Level 3 XPath API (documentInstance.evaluate) (EXSLT 関数を DOM Level 3 XPath API に公開する)
- 362391 - DOMAttrModified doesn't handle namespaced attributes properly (DOMAttrModified が名前空間が指定された属性を適切に処理できない)
- 206053 - document.getElementsByTagName('tagname') with XML document wrongly includes elements with namespace prefix in the tag name (XML 文書の document.getElementsByTagName('tagname') がタグ名の中に名前空間接頭辞を持つ要素を誤って含んでしまう)
- 22942 (entities) - Load external DTDs (entity/entities) (local and remote) if a pref is set (pref がセットされている場合には (ローカルとリモートの) 外部 DTD (実体) をロードする)
- 275196 - xml:id support (xml:id のサポート)
- xml:id 標準のページ (developerWorks、2007年4月) では、xml:id について、また XML 文書の中の要素に固有の識別子を付加する方法について学ぶことができます。
- XSLT (Extensible Stylesheet Language Transformations) 標準のページ (developerWorks、2007年4月) では、XSLT と EXSLT について、また XML 文書を別の形式に変換する方法について学ぶことができます。
- xml:id サポートのページを訪れ、xml:id に関する進行状況を知り、必要であれば、JavaScript で XPath を使って XML 名前空間での属性とローカル名 id に関するクエリーを実行してください。
- SVG improvements in Firefox 3 のページで SVG のサポートに関する改善について調べてみてください。このページには新たに追加された機能を便利な一覧で見ることができます。
- Firefox と XML に関するこれまでの記事を読んでください (Uche Ogbuji 著、developerWorks)。
- 「Firefox 1.5でのXML、第1回:XML機能の概要」(2006年3月)
- 「Firefox 1.5でのXML、第2回:基本的なXML処理」(2006年3月)
- 「XML in Firefox 1.5, Part 3: JavaScript meets XML in Firefox」(2006年8月)
- 「XML 的思索: Firefox 2.0 と XML」(2007年10月)
- 「ヒント: マルチパスXSLT」(developerWorks、Uche Ogbuji 著、2002年9月) と「ヒント: XML文書の語数を計算する」(developerWorks、Uche Ogbuji 著、2005年9月) は、Mozilla に EXSLT のサブセットが追加されることで利用可能となる XSLT の手法をいくつか解説しています。EXSLT 全般に関しては「実例で学ぶEXSLT」(developerWorks、Uche Ogbuji 著、2003年2月) を読んでください。
- XML および関連技術において IBM 認定技術者になる方法については、IBM XML certification を参照してください。
- developerWorks の XML 技術ライブラリーには、広範な話題を網羅した技術記事やヒント、チュートリアル、技術標準、IBM Redbooks などが用意されています。
- developerWorks の Web Architecture ゾーンに用意された Web 技術に特化した記事やチュートリアルを利用して Web 開発のスキルを磨いてください。
- developerWorks technical events and webcasts で最新情報を入手してください。
- Technology bookstore には、この記事や他の技術的な話題に関する本が豊富に取り揃えられています。
- developerWorks podcasts では、ソフトウェア開発者のための興味深いインタビューや議論を聞くことができます。
製品や技術を入手するために
- Mozilla ベースの Web ブラウザー、Firefox を入手してください。Firefox は標準への準拠、パフォーマンス、セキュリティー、そして確実な XML 機能を提供しています。
- developerWorks から直接ダウンロードできる IBM trial software を利用して皆さんの次期プロジェクトを構築してください。これらの試用版には DB2® や Lotus®、Rational®、Tivoli®、WebSphere® などが提供するアプリケーション開発ツールやミドルウェア製品が含まれています。
議論するために
- ディスカッション・フォーラムに参加してください。
- XML zone discussion forums に参加してください。これらのフォーラムでは XML を中心に議論が行われています。
- この記事を読んだ後、developerWorks XML zone: Share your thoughts に皆さんのコメントや意見を投稿してください。XML ゾーンの編集者がこのフォーラムの司会をしており、皆さんからの意見を歓迎しています。
- developerWorks blogs から developerWorks のコミュニティーに加わってください。

Uche Ogbuji は次世代の Web 技術によるソリューションを専門とする会社 Zepheira, LLC のパートナーです。Ogbuji 氏は XML、RDF、およびナレッジ・マネージメント・アプリケーション用のオープンソース・プラットフォームである 4Suite とその後継である Akara の中心的開発者であり、またチームによる Web 開発のための Jacqard アジャイル手法、そして Versa RDF 問い合わせ言語などの開発リーダーでもあります。彼はナイジェリア出身のコンピューター・エンジニア兼ライターとして米国コロラド州ボルダーに住み、そこで働いています。彼に関して詳しくは、彼のブログである Copia を見てください。