- XSLTは複雑なビルドシステムなしですぐに使える、Webのための標準搭載ビルドツール
- 多くの静的サイト向けビルドシステムには、複雑さ、理解の難しさ、フレームワーク依存の問題がある
- XMLとXSLTを活用すれば、ブラウザ上で直接HTMLを生成でき、動的なデータ処理やマークアップ生成が容易になる
- 主要なブラウザはすべてXSLTベースの変換をサポートしており、追加のJavaScriptや別ツールなしで利用できる
- 完璧な解決策ではないものの、Web標準に基づくシンプルで柔軟な代替手段として活用価値が高い
紹介と問題意識
- 大半の静的Webサイト開発は、データ用ファイル(
.json、.md、.txt)、別個のビルドシステム(Hugo、Next.js、Astroなど)、そしてHTML生成物という構成になっている
- ビルドシステムは複雑性を増大させ、小さなブログでさえ理解や運用がますます難しくなる
- フレームワークを排除し、シンプルなHTML、CSS、標準仕様(HTTP、URI、HTML)だけで作業しようとすると、ヘッダーやフッターの繰り返しなど保守性の面で限界が生じる
- HTML importやWeb Componentsも試したが、前者はサポートがなく、後者はJavaScriptエンジン依存の問題があるため代替にはならなかった
Webブラウザをビルドシステムとして使う
- Webブラウザ自体がさまざまなデータ変換(text/html、text/markdown、application/xmlなど)をサポートしている点に着目した
- Web仕様を深く見直し、不要な外部ツールやフレームワークなしで問題を解決する方法を模索した
XSLTの活用
- RSSフィードを見栄えよく表示したいと思い、XSLT仕様を見つけた
- XSLTはXMLデータとHTML出力構造の両方を表現できる正式な標準技術である
- 使い方は簡単
- たとえば
blog.xml にデータを整理する
- 次のようにXSLTスタイルシートを関連付ける
<?xml-stylesheet type="text/xsl" href="blog.xsl"?>
blog.xsl にはHTMLテンプレートとデータマッピング規則を書く
- テンプレート、繰り返し、変数、外部ファイルのimportなど、ほとんどのビルドシステム機能がサポートされている
実行方法と利点
- 別ツールなしでXMLファイルをWebブラウザで開くだけで、変換結果がそのままレンダリングされる
- XMLフォーマットはHTMLに似ており、人間にとって扱いやすく保守しやすいため、JSONの代わりに使っても不便さは少ない
- 主要なWebブラウザはすべてXSLTベースの変換をネイティブでサポートしており、クライアントが直接変換結果を確認できる
- JavaScript、別個のビルドツール、バンドラーが不要である点は非常に大きい
- XSLTは究極の万能解ではないが、シンプルで拡張性のあるWebビルドの代替手段である
結論
- 過去の技術(XSLT)と明確な標準の価値を再発見する
- Webブラウザをビルドシステムとして活用する方法は、Web開発のツールボックスに加える価値のある有用な選択肢である
1件のコメント
Hacker News のコメント
以前在籍していた会社は XML テンプレートに XSLT をかなり多用していて、おそらく今もそうだと思う。正直あまり良い選択ではなく、できるなら別のものに移行したがっていたはず。
JS にも問題はあるが、少なくともこうしたアルゴリズム的複雑さを直せないという状況ではない。
XSLT/XPath は 1.0 以降かなり進化している。key(index) などさまざまな機能が追加されて、処理速度はかなり向上した。Saxon のような高品質な XSLT 実装を使えば、性能問題もずっと少ない。XML を別のものに変換する際、XSLT ほど論理構造化に便利なものはあまりないと思う。
XSLT はかなり学習が難しい。どこか夢見心地の Prolog のようでもあり、本当に熟達すると数独を解くときのような快感がある。ただ、ほとんどの場合そこまで複雑なテンプレートは必要ないので、標準的な選択肢にはなりにくい。そして XML 自体も万人に好まれるフォーマットではない。
XSLT 1.0 がまだ広く使われているという点はよく分からない。2013 年の時点ですでに 1.0 はほぼ時代遅れ扱いで、XSLT 2 が使える Saxon は無料で性能も非常に良かった。大きな文書でも小さな文書でも、変換時に性能問題を経験したことは一度もない。
XSLT が登場した時代は、本文が非常に長い XML を処理するのが当たり前だった。こうして繰り返しループが入れ子になれば、当然破綻するのはむしろ自然なことだ。
商用版の Saxon を使っているのか気になる。価格も高くないし、新しい標準対応、性能、各種機能を考えると IMHO 本当に価格に見合う選択だと思う。以前使ったときは、かなり賢い最適化が入っていた記憶がある。
90〜00 年代のブラウザは互いにばらばらで、JS を導入して動作をそろえ始めた。
本当は欲しかったのは見栄えの良い CSS スタイルだったが、当時はまともに使えなかった。
時間がたつにつれ 1 つのブラウザが主導権を握り、他のブラウザもかなり似通ってきた(Highlander の法則、とはいえ Firefox もかなり健闘している)。
すでにフレームワークが当たり前になっていたため、すべてのブラウザで同じ UI をそろえる用途として定着した。そしてパラダイム自体が JSON データのレンダリングへ移っていった。
今ではサーバーで伝統的な Web ページを生成しても高速で、メモリ使用量も少ない時代だ。
こんなことを考えるのは、最近レガシーシステムの移行作業で、ページ単位の HTTP リクエスト方式(2000 年代の標準)で動くサイトを再び体験したからだ。何かアクションをするたびに再読み込みが必要だったが、むしろ React を使うシステムよりずっと速かった。
理由は、
AJAX と DOM 更新は、単に高速化のために登場したわけではない。Web のパラダイム、つまり「Web サイト / Web 文書」から抜け出すためだった。ページ全体のリロードは、文書中心のパラダイムでは意味のある方式だ。HN のような単純な例では、こうした構造が非常によく合う。多くのサイトは JS フレームワークなしでもこの構造で十分動く。
だが「誰もがページ全体リロードに回帰できる」というのは現実とかけ離れている。実際、複雑なインタラクションを求める「Web アプリケーション」では、ページ全体のリロードは非常に悪い UX だ。
要するに、
「Web サイト」「Web 文書」「簡単なフォーム」などはページ全体リロードだけで十分なことが多いが、
「Web アプリケーション」のように複雑なデータ画面や操作が必要な場合はそうではない。
当時のタイムラインについての自分の記憶は少し違う。JS はブラウザ動作の統一化というより、最初からインタラクティブ要素のために使われていた(DHTML、AJAX など)。本当にレイアウトを合わせるのは、ブラウザごとのハックや UA 判定にほぼ依存していた。CSS が強力になっても一貫性の問題は簡単には解決しなかった。CSS garden、セマンティックマークアップ、テーブル多用などが当時の空気感で、最初の ACID テストを通るまでにも本当に長い時間がかかった。フレームワークが UI の一貫性にどれほど影響したのかは懐疑的だ。jQuery 以降は、むしろ CSS 自体が視覚的一貫性の主役だった。
もちろん個人の記憶かもしれない。
最新の技術スタックでは、サーバーレンダリングの伝統的な Web ページが高速かつ軽量だという点に同意する。
私の .NET/Kestrel/SQLite スタックでは、SSR の応答が 4ms を超えることはまずなく、ほとんどは 100 マイクロ秒台だ。各ページで複数クエリと複雑な join を使い、ビューに合ったデータ形状を作っている。
100,000 行のテーブルを作るような極端なケースでも、HTML 文字列を組み立てる前のデータ加工をうまくやれば性能は大きく向上する。LINQ の性能も非常に良いが、行ごとにコレクションを作るとデータ件数が増えるほどかえって極めて非効率になる。
私の経験では、HTML テンプレートエンジンとデータベースをできるだけ近くに置くのが、性能最適化には最も良かった。最終的に DOM はただのバイトストリームだ。わざわざ複雑な AST やパーサーを作らなくても、StringBuilder と SQL クエリの組み合わせで十分だ。
こうした単純な方式への反論は、いつも「開発者に HTML エスケープを任せられない」というセキュリティ担当の懸念だけだった。
「最新技術を使えばサーバーで昔ながらの古典的 Web ページを十分さばける」という話も、ネットワークレイテンシが高ければまったく別の話になりうる。
参考リンク
2000 年代のエンタープライズ XML はあまりに肥大化し、技術が時代遅れに見えるようになって、結局みんな JSON の「すっきり感」に夢中になった。実際には XSLT や XPath のような技術はすでに完成度が高く、今でも悩んでいる多くの問題を解決してくれていた。
私も昔、XSLT include をひどく乱用して、PHP のストリームラッパーで
<xsl:include href="mycorp://invoice/1234">のようなものを使っていた。正直、今ではやや古臭い感覚かもしれないが、ブラウザにローカル XSLT を処理させるのは今でも不安だ。昔は互換性の地雷原だったからだ。
XML の「基本」要素が JSON ではいまだに恋しい。たとえば本当に標準化された仕様やスキーマ定義などは XML のほうがずっと優れていて、JSON が追いつくのにほぼ 10 年かかった。
最後に XML を本格的に触ったのは EXI という転送技術だった。XML 文書を圧縮バイナリストリームに変換する方式で、構造体 ↔ アスキー変換 ↔ 圧縮 / 転送 ↔ 逆変換はもちろん面倒だった。今は protobuf や gRPC が主流だが、もし XML が使われ続けていたら、すべてが互換性のある標準ベースという(自分の理想化した想像の中の)世界が広がっていたかもしれない。実際には protobuf/gRPC と JSON API の間に巨大な壁ができたが、それはそれで良いことだったのかもしれない。
XML は悪くないフォーマットだと思う。量が多くて冗長ではあるが、YAML と比べれば精密さと表現力の面ではるかに優れている。
XPath は慣れるまで難しいが、試してみれば結局やりたいことはできる。
XSLT は完全に正気を失った概念だと思う。追放されるべきだ。
Rimworld というゲームは、すべての設定データを XML で保存し、XPath でモッディング可能にしている。この組み合わせは本当に強力だ。ローカルデータのカスタマイズにはこれ以上ない。ただ、多くのゲームは XML が「古い」というレッテルのせいで、こういうものを使いたがらないようだ。
Rimworld の XPath モッディング公式ドキュメント
2000 年代初頭のエンタープライズ XML が肥大化したという話は本当にその通りだ。もともと XML は、SGML を Web で使えるよう簡素化したもので、マークアップの伝達や語彙拡張を目的としていた。結局生き残ったのは SVG と MathML だけだった。Web ブームに乗って W3C/MS は SOAP や WS-* 仕様などを次々と乱発した。一時は Scheme の骨格を持つ XSLT のような言語まで XML に無理やり押し込めた、狂気に満ちた時代だった。JavaScript でさえ名前だけは Java にあやかった、そんな時代だ。
XPath は名前空間のせいで、うんざりするほど冗長なクエリを書かないといけないのが残念だ。
今でも XSLT で自分のフィードをスタイリングして使っている。
RSS フィードのサンプル
XSLT のサンプル
こういうのを見ると、ブログというものは単なる RSS フィードであるべきだったのではと思わされる。
XML が本来こういうことまでできるのをいつも忘れてしまう。何だか直感的には不自然に感じる。
本当に見事に作られている。他の人たちもこういう例をもっと創造的に取り入れてみてほしい。
最初の職場(19 歳のとき)で Google Search Appliance のカスタマイズを担当したことがある。何百万円もする黄色い Dell サーバーに CentOS を入れ、Google っぽい Python と CIFS 文書の全文検索を導入するプロジェクトだった。
2011 年ごろは XHTML が主流で、Google Search Appliance ではバックエンドの XML データを XSLT で XHTML に変換していた。サンプルテンプレートを壊しながら、社内イントラネット向けの怪しい UI を作り、Coldfusion、StackOverflow、W3Schools など既存資産を継ぎはぎして押し込んだ。
この経歴はすぐ履歴書から消した。その後 DoD(国防総省)下請け企業が、私を「XML の専門家」だとして文書システム近代化プロジェクトに何度も呼ぼうとしてきて、うんざりした。
次に JSX を使って JSON から TypeScript インターフェースに配列を回すようなことをしてため息をつくときは、私のことを思い出してほしい。少なくとも XSLT でそれをやるよりはましだ。
私はたしかに単純さを求める人間だ。原始人の readme みたいに簡単な文書が好きだし、たまには原始人のようにキーボードを振り回している気分にもなる。Web サイトはやらないし、XSLT もよく分からない。たまに XML でハックして、ユーザー向けのものを見せたくなる。ファイル形式が多すぎて頭が痛い。それでも見た目の良いものは好きだ。自分もこれを使うかもしれない。
仕様を読んでくれてありがとう、そしてツールを作ってくれてありがとう。
XML は冗長で複雑に見えると言われがちだが、実際に扱ってみると素晴らしいフォーマットだ。
DTD で検証し、XSLT で出力して人間に見やすくできる。
私にとって XML は C++ のようなテキストフォーマットだ。成熟していて、「電池付き」で、強力で、どんな言語ともつなげられる。
古く成熟した言語がそうであるように、XML もまた変人向けの代物だとけなすのが流行になってしまったのは残念だ。用途に合わないなら使わなければいいが、そこまで過剰に嫌う理由はない。
「ブラウザで XSLT がそのまま動く」という話に驚いた。最後に XSLT を使ったのは 20 年前だが、そのころは巨大で複雑なエンタープライズ Java のせいで、XSLT 固有の美学がすべて埋もれてしまう感じだった。
でも XSLT がブラウザで標準動作するなら、ホストフレームワーク不要の真の静的テンプレートという聖杯は目の前にあったのだろうか?
ブラウザは XSLT 1.0 しかサポートしていない。そしてこれでさえ今後なくなるかもしれないという話もある。むしろブラウザが 3.0 まで対応してくれれば、静的 Web ページ生成にものすごく使いやすくなるのに惜しい。
「巨大エンタープライズ Java」タワーを必ず使わなければならなかったわけではない、という経験もある。こちらは tomcat といくつかの apache ライブラリだけで使っていて、かなりうまく動いていた。CMS では XML で作った HTML に個人化情報を XML タグの形で入れ、サーバーサイドのキャッシュプロキシのおかげで変換も高速で、大量トラフィックにも対応できた。要は XSLT の出力ストリームをすぐクライアントへ流し、メモリ全体にバッファしないことが重要だった。
今なら wasm ベースで何でもブラウザで動かせるが、初期の JS は致命的で、デザイナーは Photoshop の PSD を渡してくれるだけでもありがたい時代だった。Google Maps や Gmail が出てきたころ、javascript heavy な UI を必死に作り、しかも当時の Netscape と Internet Explorer の両方をサポートしなければならない、本当の地獄だった。
XHTML ブームが始まったのも、実はまさにこの「静的テンプレートの聖杯」が理由だった。ただ実際に分かっている人たちは符丁のように言葉を濁し、誰もあからさまには語らないという妙な空気があった。
2008 年にブラウザ内 XSLT サイトで働いたことがあり、その前の 2000 年代初頭にもすでにサポートされていた。
Chrome には libxslt、Firefox には Transformiix という 1.0 エンジンが搭載されている。Chrome は exsl:node-set だけをサポートし、Firefox はさまざまな EXSLT 拡張をサポートしている(全部ではない)。
簡単な XSLT プロセッサ情報と利用可能な拡張の一覧を表示する小さなツールも公開している。
GitHub - xslt-detect-ext
ブラウザで
out/detect.xsltファイルをドラッグすれば情報を確認できる(Chrome、Firefox)。Safari は昔の Windows 版では動かなかった。90 年代に高校生で「Web デザイナー」と呼ばれていたころ、DSSSL 方言のパイプラインを使ってニュースフィードからサイトを自動生成していた。今でも XSLT 変換は好きだ。bananas XI reader のようなツールを使って、実際のテキスト変換やテンプレート作業も自分でしている。
だが、こうしたツール群を本当に好きな人は非常に少なく、結局自分の後任が入ると導入した技術はすぐ消えていくことが多かった。
bananas XI reader
2000 年代初頭の XML と XSLT ブームがどれほど激しかったかを示すと、私が働いていた会社では XML をリアルタイム速度でパースし、XSLT までチップ上で直接処理する ASIC を作っていた。当時は未来のインターネットがすべて XML/XSLT で動くと信じられていた。
実際、この会社は Intel に買収され、その技術は SSE アクセラレータのほうに取り込まれた。
ASIC で XML 解釈や XSLT までそのまま処理できる構造が主流になっていたら、今ごろ Web サイトはものすごく高速だっただろうと想像してしまう。
IBM は今でも、これに近い機能を内蔵したハードウェア(DataPower Gateway)を販売している。