👊

[XSLT 3.0]ビルトインmodeで未定義matchを直ちに失敗させる

に公開

https://adventar.org/calendars/11635

XSLT 3.0デバッグまわり Advent Calendar 2025 の3日目。

今日も小ネタ。

matchするテンプレートがないときの処理 xsl:mode/@on-no-match

matchテンプレートに@modeを設定し、<xsl:apply-templates>のときにその@modeを指定することでmode毎に異なったテンプレートが適用できます。「目次処理用」「本文処理用」「索引処理用」とかですね。何も指定していないときは無名のmodeとしてまとめられます。

3.0では<xsl:mode />という、modeを明示する機構があります。ここでは@on-no-match@on-multiple-matchという属性が指定可能です。
前者は「matchするテンプレートがそのmodeに無いとき」後者は「matchするテンプレートがそのmodeに複数あるとき」の処理を決めるものです。

1日目の記事で、「うっかり想定していない構造に陥ったときのためにpriorityを下げた@match="*"のテンプレートを用意しておく」という方法を示しました。これは、デフォルトだとmatchするテンプレートがないとき「テキストのみコピー」(text-only-copy)の挙動を取ってしまうためです。
こうするしかなかった。

しかし今は違う!(ギュッ)
3.0でも既定はtext-only-copyです。
しかし、@on-no-matchに指定可能な値;matchするmodeがないときに使えるビルトイン・テンプレート規則はいくつもあります。

  • deep-copy
  • shallow-copy
  • deep-skip
  • shallow-skip
  • text-only-copy
  • fail

それぞれのビルトインテンプレートがどのように振る舞うかはXSLT 3.0の仕様書に対応するテンプレートの書き方が記載されています。

つまるところ、failをここで指定すれば、matchするものが無ければその時点で処理が失敗します。
もう優先度の低いテンプレートを作ってxsl:message/@terminate="yes"を書く必要はないわけです。

参考資料

https://www.w3.org/TR/xslt-30/#built-in-rule

組版・ドキュメンテーション勉強会

Discussion