XSLT3.0への道(22) 配列型

次々と技術が進化するのでとてもキャッチアップできませんが、2月7日はXSLT 3.0にとって特別な日になったようです.

XSL Transformations (XSLT) Version 3.0
W3C Candidate Recommendation 7 February 2017


ついにというかようやくXSLT 3.0はW3Cの最終Candidate Recommendation(勧告候補)となりました.そしてXSLT 3.0のインプリメントXPath 3.1のデータモデルをサポートします.(というかしなければなりません.)

XML Path Language (XPath) 3.1
W3C Proposed Recommendation 17 January 2017

XPath 3.1で重要なデータ型の追加になったのはマップ型(map)と配列型(array)です.この日に同時にリリースされたSaxonでちゃんとサポートされたようなので配列型をすこし触ってみました.といってもちょうどSaxon PE(プロフェッショナルエディション)のバージョンアップの期間が切れてしまい、新しいのはオープンソースのHE(ホームエディション)でしかテストできません.

例として、用紙とその幅、高さを表現することを考えてみました.

Letterは幅215.9mm、高さ279.4mm
Legalは幅215.9mm、高さ355.6mm
B4は幅250mm、高さ353mm
A4は幅210mm、高さ297mm

というようなものです.これは今まではitem()*で表すしか手がなかったように思えます.例えば

<xsl:variable name="paperInfoSeq" as="item()*" select="('Letter',215.9,279.4,'Legal',215.9,355.6,'B4',250,353,'A4',210,297)"/>

という感じです.あまりきれいではありません.用紙単位に情報がグルーピングできないからです.配列を使えば次のように素直に表現できます.

<xsl:variable name="paperInfoArray" select="[('Letter',215.9,279.4),('Legal',215.9,355.6),('B4',250,353),('A4',210,297)]"/>

さっそく次のようなスタイルシートを書いてみます.oXygen 18.1でやっていますが、まだoXygenは古いSaxonをバリデーションに使用しているのでボロボロエラーが出ますが気にせずコーディングします.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="xs array"
    version="3.0">
    
    <xsl:function name="ahf:returnPaperInfoArray" as="array(item()*)">
        <xsl:sequence select="[('Letter',215.9,279.4),('Legal',215.9,355.6),('B4',250,353),('A4',210,297)]"/>
    </xsl:function>

    <xsl:template match="/">
        <xsl:variable name="arrayVar" as="array(item()*)" select="ahf:returnPaperInfoArray()"/>
        <xsl:for-each select="1 to array:size($arrayVar)">
            <xsl:variable name="paperInfo" as="item()*" select="$arrayVar(position())"/>
            <xsl:message select="concat('[',position(),'] paper=',string($paperInfo[1]),' width=',string($paperInfo[2]),'mm height=', string($paperInfo[3]),'mm')"/>
        </xsl:for-each>
    </xsl:template>
    
</xsl:stylesheet>

最初のahf:returnPaperInfoArrayという関数は、配列がXPath 3.1では「型」になったことを確認するものです.as="array(item()*)で型として記述できます."["と"]"で配列のコンストラクトができます.これは次のようにも記述できます.

<xsl:sequence select="array{('Letter',215.9,279.4),('Legal',215.9,355.6),('B4',250,353),('A4',210,297)}"/>

その下のテンプレートは、配列を$arrayVarに格納し、配列の各要素をxsl:messageで表示させています.配列のサイズはarray:size()で取得できます.

これを動かした結果は次のようなものになります.

イメージ 1

ここで大事なことは配列の要素(member)の自由度が高いことです.配列のメンバーには関数やマップなども可能なはずです、Saxon Heでは残念ながらここまでしか試せませんが、新しいSaxon PE 9.7.0.15が手に入れられたら試してみたいと思います.