XSLT3.0への道(9) パターン (その2)

次にPathPatternで変更されている点にRootedPatternの追加があります.RootedPatternは次のように定義されます.
 
[7]  RootedPattern ::= ( VarRefRoot | DocCall | IdCall | ElementWithIdCall | KeyCall ) (('/' | '//') RelativePathPattern)?
[8]  VarRefRoot ::= VarRef
[9]  RelativePathPattern ::= PatternStep (('/' | '//') PatternStep)*
[10] PatternStep ::= PatternAxis? NodeTest PredicateList
[11] PatternAxis ::= (('child' | 'attribute' | 'descendant' | 'descendant-or-self') '::') | '@'
[12] DocCall ::= 'doc' '(' ArgValue ')'
[13] IdCall  ::= 'id' '(' ArgValue (',' ArgValue )? ')'
[14] ElementWithIdCall ::= 'element-with-id' '(' ArgValue (',' ArgValue )? ')'
[15] KeyCall ::= 'key' '(' ArgValue ',' ArgValue (',' ArgValue )? ')'
[16] ArgValue ::= Literal | VarRef
 
IdCallとKeyCallはXSLT2.0にもIdKeyPatternとして存在しました.
 
[6] IdKeyPattern ::='id' '(' IdValue ')' | 'key' '(' StringLiteralXP ',' KeyValue ')'
 
RootedPatternはこれをさらに拡張したものと言えるでしょう.
この拡張によりテンポラリツリーの要素だけにマッチするテンプレートの記述が可能になります.例えば索引のindextermの処理は次のようにな感じでRootedPatternが使えるようになるでしょう.
 
<!--索引用のデータ(ソートキー、表示用文字列など)を作成/ソート-->
<xsl:variable name="index" as="document-node()">
  <xsl:document>
    <xsl:for-each select="//indexterm">
      <xsl:sort lang="ja"/>
      <xsl:element name="{name()}">
        ...
      </xsl:element>
    </xsl:for-each>
  </xsl:document>
</xsl:variable>
 
<!-- 索引の出力処理テンプレート(実際はちょっと複雑) -->
<xsl:template match="$index/indexterm">
  ...
</xsl:template>
 
<!-- メインからの呼び出し -->
<xsl:apply-templates select="$index/indexterm[1]"/>

あとRootedPatternにより記述が可能になるパターンは次のような例があります.
 
<xsl:template match="doc('draft.xml')//para">
<xsl:template match="id('id_00010')/person"> <!-- XSLT2.0にある -->
<xsl:template match="element-with-id('id_00010')/person">
<xsl:template match="key('personByCompany','IBM')/person"> <!-- XSLT2.0にある -->
 
最初のmatch="doc('draft.xml')//para"はまだ使う場合が考えられますが、あとは特殊な用途でないと使う機会は限られるように思われます.
 
ちなみにid()とelement-with-id()ですが、XQuery 1.0 and XPath 2.0 Functions and Operators (Second Edition)によると、id関数はXMLスキーマで要素の属性がxs:IDの属性が与えられ、それをschema-awareなXSLTプロセッサで処理しないと期待した結果が得られないようです.このid関数の互換性を保証するために、element-with-id が導入されています.
 
 
次にXSLT2.0(XPath2.0)ではノードの集合演算に使われてきたunion、intersect、exceptがパターンで使用できるようになります.例えば次のような例が可能になるでしょう.
 
<xsl:variable name="japaneseBooks" select="//book[@lang='ja']" as="element()?"/>
<xsl:variable name="javaBooks" select="//book[@category='Java']" as="element()?"/>
 
<!-- 日本語かカテゴリがJavaの本にマッチ -->
<xsl:template match="$japaneseBooks union $javaBooks">
 
<!-- 日本語でカテゴリがJavaの本にマッチ -->
<xsl:template match="$japaneseBooks intersect $javaBooks">
 
<!-- 日本語でカテゴリがJava以外の本にマッチ -->
<xsl:template match="$japaneseBooks except $javaBooks">
 
最後はQualifiedPatternです.任意のパターンを書いて括弧で囲み右に制約条件を書くことができます.例えば次のように書けるのと考えられます.
 
<!-- 日本語でカテゴリがJavaで2000円以下の本にマッチ -->
<xsl:template match="($japaneseBooks intersect $javaBooks)[xs:integer(@price) le 2000]">
 
まだドラフトなので解説や例が十分でないと思われる点もありますが、パターンは大幅に変わることは間違いないようです.